今天用了下Lucene,发现网上虽然也有不少介绍它的文档,不过很多都偏向介绍概念呀、设计或者是一些更为深入的东西,对于其入门使用的介绍性的文档并不多,就写了这么一篇。
Lucene
基本使用介绍
本文的目的不在于对
Lucene
的概念和设计这些进行介绍,仅在于介绍怎么样去使用
Lucene
来达到自己想要的几种常见的全文检索的需求,如果想深入了解
Lucene
的话本文不会带给你什么收获的。看完本文后想更深入的了解
Lucene
请访问:http://
lucene.apache.org
一.
概述
随着系统信息的越来越多,怎么样从这些信息海洋中捞起自己想要的那一根针就变得非常重要了,全文检索是通常用于解决此类问题的方案,而
Lucene
则为实现全文检索的工具,任何应用都可通过嵌入它来实现全文检索。
二.
环境搭建
从
lucene.apache.org
上下载最新版本的
lucene.jar
,将此
jar
作为项目的
build path
,那么在项目中就可以直接使用
lucene
了。
三.
使用说明
3.1.
基本概念
这里介绍的主要为在使用中经常碰到一些概念,以大家都比较熟悉的数据库来进行类比的讲解,使用
Lucene
进行全文检索的过程有点类似数据库的这个过程,
table---
à
查询相应的字段或查询条件
----
à
返回相应的记录,首先是
IndexWriter
,通过它建立相应的索引表,相当于数据库中的
table
,在构建此索引表时需指定的为该索引表采用何种方式进行构建,也就是说对于其中的记录的字段以什么方式来进行格式的划分,这个在
Lucene
中称为
Analyzer
,
Lucene
提供了几种环境下使用的
Analyzer
:
SimpleAnalyzer
、
StandardAnalyzer
、
GermanAnalyzer
等,其中
StandardAnalyzer
是经常使用的,因为它提供了对于中文的支持,在表建好后我们就需要往里面插入用于索引的记录,在
Lucene
中这个称为
Document
,有点类似数据库中
table
的一行记录,记录中的字段的添加方法,在
Lucene
中称为
Field
,这个和数据库中基本一样,对于
Field Lucene
分为可被索引的,可切分的,不可被切分的,不可被索引的几种组合类型,通过这几个元素基本上就可以建立起索引了。在查询时经常碰到的为另外几个概念,首先是
Query
,
Lucene
提供了几种经常可以用到的
Query
:
TermQuery
、
MultiTermQuery
、
BooleanQuery
、
WildcardQuery
、
PhraseQuery
、
PrefixQuery
、
PhrasePrefixQuery
、
FuzzyQuery
、
RangeQuery
、
SpanQuery
,
Query
其实也就是指对于需要查询的字段采用什么样的方式进行查询,如模糊查询、语义查询、短语查询、范围查询、组合查询等,还有就是
QueryParser
,
QueryParser
可用于创建不同的
Query
,还有一个
MultiFieldQueryParser
支持对于多个字段进行同一关键字的查询,
IndexSearcher
概念指的为需要对何目录下的索引文件进行何种方式的分析的查询,有点象对数据库的哪种索引表进行查询并按一定方式进行记录中字段的分解查询的概念,通过
IndexSearcher
以及
Query
即可查询出需要的结果,
Lucene
返回的为
Hits
.
通过遍历
Hits
可获取返回的结果的
Document
,通过
Document
则可获取
Field
中的相关信息了。
通过对于上面在建立索引和全文检索的基本概念的介绍希望能让你对
Lucene
建立一定的了解。
3.2.
全文检索需求的实现
索引建立部分的代码:
private
void
createIndex(String indexFilePath) throws Exception
{
IndexWriter iwriter
=
getWriter(indexFilePath);
Document doc
=
new
Document();
doc.add(Field.Keyword(
"
name
"
,
"
jerry
"
));
doc.add(Field.Text(
"
sender
"
,
"
bluedavy@gmail.com
"
));
doc.add(Field.Text(
"
receiver
"
,
"
google@gmail.com
"
));
doc.add(Field.Text(
"
title
"
,
"
用于索引的标题
"
));
doc.add(Field.UnIndexed(
"
content
"
,
"
不建立索引的内容
"
));
Document doc2
=
new
Document();
doc2.add(Field.Keyword(
"
name
"
,
"
jerry.lin
"
));
doc2.add(Field.Text(
"
sender
"
,
"
bluedavy@hotmail.com
"
));
doc2.add(Field.Text(
"
receiver
"
,
"
msn@hotmail.com
"
));
doc2.add(Field.Text(
"
title
"
,
"
用于索引的第二个标题
"
));
doc2.add(Field.Text(
"
content
"
,
"
建立索引的内容
"
));
iwriter.addDocument(doc);
iwriter.addDocument(doc2);
iwriter.optimize();
iwriter.close();
}
private
IndexWriter getWriter(String indexFilePath) throws Exception
{
boolean append
=
true
;
File file
=
new
File(indexFilePath
+
File.separator
+
"
segments
"
);
if
(file.exists())
append
=
false
;
return
new
IndexWriter(indexFilePath,analyzer,append);
}
3.2.1. 对于某字段的关键字的模糊查询
Query query
=
new
WildcardQuery(
new
Term(
"
sender
"
,
"
*davy*
"
));
Searcher searcher
=
new
IndexSearcher(indexFilePath);
Hits hits
=
searcher.search(query);
for
(
int
i
=
0
; i
<
hits.length(); i
++
)
{
System.
out
.println(hits.doc(i).
get
(
"
name
"
));
}
3.2.2. 对于某字段的关键字的语义查询
Query query
=
QueryParser.parse(
"
索引
"
,
"
title
"
,analyzer);
Searcher searcher
=
new
IndexSearcher(indexFilePath);
Hits hits
=
searcher.search(query);
for
(
int
i
=
0
; i
<
hits.length(); i
++
)
{
System.
out
.println(hits.doc(i).
get
(
"
name
"
));
}
3.2.3. 对于多字段的关键字的查询
Query query
=
MultiFieldQueryParser.parse(
"
索引
"
,
new
String[]
{
"
title
"
,
"
content
"
}
,analyzer);
Searcher searcher
=
new
IndexSearcher(indexFilePath);
Hits hits
=
searcher.search(query);
for
(
int
i
=
0
; i
<
hits.length(); i
++
)
{
System.
out
.println(hits.doc(i).
get
(
"
name
"
));
}
3.2.4. 复合查询(多种查询条件的综合查询)
Query query
=
MultiFieldQueryParser.parse(
"
索引
"
,
new
String[]
{
"
title
"
,
"
content
"
}
,analyzer);
Query mquery
=
new
WildcardQuery(
new
Term(
"
sender
"
,
"
bluedavy*
"
));
TermQuery tquery
=
new
TermQuery(
new
Term(
"
name
"
,
"
jerry
"
));
BooleanQuery bquery
=
new
BooleanQuery();
bquery.add(query,
true
,
false
);
bquery.add(mquery,
true
,
false
);
bquery.add(tquery,
true
,
false
);
Searcher searcher
=
new
IndexSearcher(indexFilePath);
Hits hits
=
searcher.search(bquery);
for
(
int
i
=
0
; i
<
hits.length(); i
++
)
{
System.
out
.println(hits.doc(i).
get
(
"
name
"
));
}
四. 总结
相信大家通过上面的说明能知道
Lucene
的一个基本的使用方法,在全文检索时建议大家先采用语义时的搜索,先搜索出有意义的内容,之后再进行模糊之类的搜索,
^_^
,这个还是需要根据搜索的需求才能定了,
Lucene
还提供了很多其他更好用的方法,这个就等待大家在使用的过程中自己去进一步的摸索了,比如对于
Lucene
本身提供的
Query
的更熟练的掌握,对于
Filter
、
Sorter
的使用,自己扩展实现
Analyzer
,自己实现
Query
等等,甚至可以去了解一些关于搜索引擎的技术
(
切词、索引排序
etc)
等等。