实现简单的搜索功能
对特定项的搜索
Term t = new Term("fieldName", "key workd");
Query query = new TermQuery(t);
TopDocs topDocs = searcher.search(query, 10);
ScoreDocs scoreDocs : topDocs
解析用户输入的查询表达式:QueryParser
QueryParser parser = new QueryParser(Version.LUCENE_30, "contents", new SimpleAnalyzer());
查询表达式
|
匹配文档
|
java
|
默认匹配java项的文档
|
java junit
java or junit
|
默认包含java和junit中一个或两个的文档
|
+java +junit
java AND junit
|
默认域中同时包含java和junit文档
|
title:ant
|
title域中包含ant项的文档
|
title:extreme
-subject:sports
title:extreme AND not subject:sports
|
title域中包含extreme且subject域中不包含sports的文档
|
(agile OR extreme) AND methogy
|
默认域中包含methodology且包含agile和extreme中的一个或两个的文档
|
title:"junit in action"
|
title域为junit in action的文档
|
title:"junit action" ~5
|
title域中junit和action之间距离小于5的文档
|
java*
|
包含由java开头的项的文档
|
java~
|
包含与单词java相近的项的文档,如lava
|
lastmodified:[1/1/09 TO 12/31/09]
|
lastmodified域值在2009年1月1号和2009年12月31号之间的文档。
|
使用IndexSearcher类
创建IndexSearcher类
Directory dir = FSDirectory.open(new File("/data/index/data"));
IndexReader reader = IndexReader.open(dir);
IndexSearcher searcher = new IndexSearcher(reader);
是IndexReader 完成了诸如打开所有索引文件和提供底层reader API的繁重工作,打开一个IndexReader需要较大的系统开销,因此最好在索引期间都重复使用同一个IndexReader实例。只有必要的时候才建议打开新的IndexReader。
还可以直接从索引目录中直接创建IndexSearcher,这种情况下系统会在后台建立自己私有的IndexReader。如果关闭IndexSearcher,也会关闭这个私有的IndexReader。
IndexReader.reopen()来获取新IndexReader的有效手段,重启的IndexReader能在耗费较少系统资源的情况下使用当前reader来获取索引中所有的变更信息。
//这段代码要是线程安全的
IndexReader newrReader = IndexReader.reopen();
if(reader != newReader) {
reader.close();
reader = newReader;
searcher = new IndexSearcher(reader);
}
实现搜索功能
IndexSearcher
|
使用时刻
|
TopDocs search(Query query, int n)
|
直接进行搜索,int n参数表示返回的评分最高的文档数量
|
TopDocs search(Query query, Filter filter, int n )
|
搜索受文档子集约束,约束条件基于过滤策略
|
TopFieldDocs search(Query query, Filter filter, int n, Sort sort)
|
接受文档子集的约束,约束条件基于过滤策略,结果排序通过自定义的Sort完成
|
void search(Query query, Collector results)
|
当使用自定义文档访问策略时使用,或者不想以默认的前N个搜索结果排序策略收集结果时使用
|
void search(Query query, Filter filter, Collector results)
|
同上,区别在于结果文档只有传入过滤策略时才能被接收
|
使用TopDocs
TopDocs方法或属性
|
返回值
|
totalHits
|
匹配搜索条件的文档数量
|
scoreDocs
|
包含搜索结果的ScoreDoc对象数组
|
getMaxScore
|
如果已经完成排序(当通过域进行排序时,程序需要分别控制是否对该域进行评分计算)则返回最大评分
|
搜索结果分页
1.将首次搜索获得的多页结果收集起来并保存在ScoreDocs和IndexSearcher实例中,并在用户换页浏览时展现这几页结果
2.每次用户换页时都重新换页查询
近实时搜索
IndexSearcher search = new IndexSearcher(reader);
IndexReader newrReader = IndexReader.reopen();
if(reader != newReader) {
reader.close();
reader = newReader;
searcher = new IndexSearcher(newReader );
}
理解Lucene的评分机制
lucene如何评分
使用explain()理解搜索结果评分
Explanation explanation = searcher.explain(query, match.doc);
Lucene的多样化查询
通过项进行搜索:TermQuery类
Term t = new Term("fieldName", "java");
Query query = new TermQuery(t);
可以搜索Index.NOT_ANALYZED
在指定的项范围类搜索:TermRangeQuery类
索引中的各个Term对象会按照字典编排顺序进行排序,并允许在Lucene的TermRangeQuery对象提供的范围内进行文本项的直接搜索。
TermRangeQuery query= new TermRangeQuery("title2", "d", "j", true, true); //true包含边界
在指定的数字范围内搜索:NumericRangeQuery类
NumericRangeQuery query = new NumericRangeQuery.newIntRange("pubmonth", 200605, 200609, true, true);
precisionStep 参数,如果索引时变了,搜索期间输入(如果的话!)的参数也要相同
通过字符串搜索:PrefixQuery
搜索程序使用PrefixQuery类搜索包含以指定字符串开头的项的文档。
Term term = new Term("category", "/technology/computers/programing");
PrefixQuery query = new PrefixQuery(term); // 以/technology/computers/programing开头
组合查询:BooleanQuery类
通过使用BooleanQuery类可以将本章讨论的各种查询类型组合成复杂的查询方式,而BooleanQuery本身是一个Boolean子句的容器。
public void add(Query query, BooleanClause.Occur occur)
BooleanClause.Occur.MUST
BooleanClause.Occur.SHOULD
BooleanClause.Occur.MUST_NOT
BooleanQuery对象还可以作为另一个BooleanQuery对象的子句
TermQuery searchQuery = new TermQuery(new Term("subject", "search"));
Query books2010 = NumericRangeQuery.newIntRange("pubmonth", 201001, 201012, true, true);
BooleanQuery searchingBooks2010 = new BooleanQuery();
searchingBooks2010.add(searchQuery, BooleanClause.Occur.MUST); //该条件是必须的,相当于AND
searchingBooks2010.add(books2010, BooleanClause.Occur.SHOULD);//该条件是非必须的,相当于OR
MUST_NOT 相当于非
通过短语搜索:PhraseQuery类
PhraseQuery query = new PhraseQuery();
query.setSlop(slop); //两个项位置直接允许的
最大间隔距离称为slop
for(String word : phrase) {
query.add(new Term("field", word)); //添加短语项序列
}
支持2个以上的phrase查询
项之间的距离越小,具有的权重也就越大。距离越大的匹配其评分就越低。
QueryParser: "quick fox" ~3 为quick 项和fox项生成一个slop因子为3的PhraseQuery对象。
通配符查询:WildcardQuery类
Query query = new WildcardQuery(new Term("contents", "?ild*")); //对评分没有影响
搜索类似项:FuzzyQuery类
FuzzyQuery query = new FuzzyQuery(new Term("contents", "wuzza")); //即模糊查询,实际索引的是fuzza,但是却可以通过wuzza 查到fuzza
匹配所有文档:MathcAllDocsQuery类
Query query = new MatchAllDocsQuery(field);
理解查询表达式 QueryParser
Query.toString 使用该方法查看查询表达式被QueryParser对象解析后的内容
TermQuery
QueryParser parser= new QueryParser(Version.LUCENE_30, "subject", analyzer); //默认是subject 域
Query query = parser.parse("computers"); //内容
即: subject:computers
项范围查询
QueryParser parser= new QueryParser(Version.LUCENE_30, "subject", analyzer); // 默认是
subject 域
parser.parse("title2:[Q TO V]"); //确认边界在搜索范围内
parser.parse("title2:{Q TO \"Tapestry in action\"}"); //确认边界在搜索范围外
QueryParser.setLowercaseExandedTerms(false) ,这样的话程序不会对输入的文本进行分析。
数值范围搜索和日期范围搜索
前缀查询和通配符查询
Query q = new QueryParser(Version.LUCENE_30, "field", analyzer).parse("PrefixQuery*");
setAllowLeadingWildcard 支持项开端包含通配符,但是会牺牲掉一些程序性能。
布尔操作符
QueryParser parser = new QueryParser(Version.LUCENE_30, "field", analyzer);
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
针对某项的否定操作必须与至少一个非否定项的操作联合起来进行,否则程序不会返回结果
布尔查询操作符的快捷方式
详细语法
|
快捷语法
|
a AND b
|
+a +b
|
a OR b
|
ab
|
a AND NOT b
|
+a -b
|
短语查询
"fox brown ~5" 双引号是短语查询
模糊查询
parser.parse("kountry~");
MatchAllDocsQuery
*:*
分组查询
使用( )构建复杂的嵌套查询子句
(agile OR extreme) AND methodology
域选择
为子查询设置加权
junit^2.0 testing
是否一定要使用QueryParser