简介
对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。
可通过两种方法创建查询对象:
- 使用Lucene提供Query子类
Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,WildcardQuery 统配查询 各种Point的数字范围查询等。
- 使用QueryParse解析查询表达式
Lucene QueryPaser包中提供了两类查询解析器:
传统的解析器:QueryParser和MultiFieldQueryParser
基于新的 flexible 框架的解析器:StandardQueryParser
TopDocs
Lucene搜索结果可通过TopDocs遍历,TopDocs类提供了少量的属性,如下:
| 方法或属性 | 说明 |
|---|---|
| totalHits | 匹配搜索条件的总记录数 |
| scoreDocs | 顶部匹配记录 |
注意:
Search方法需要指定匹配记录数量n:search(query, n)
TopDocs.totalHits:是匹配索引库中所有记录的数量
TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参 数n
TermQuery
根据关键词查询
需要指定要查询的域以及要查询的关键词
TermQuery,通过项查询,
TermQuery: 不使用分析器所以建议匹配不分词的Field域查询,比如订单号、分类ID号等。
指定要查询的域和要查询的关键词。
import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.IntPoint;import org.apache.lucene.index.DirectoryReader;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.Term;import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;import org.apache.lucene.queryparser.classic.QueryParser;import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser;import org.apache.lucene.search.*;import org.apache.lucene.search.spans.SpanNearQuery;import org.apache.lucene.search.spans.SpanQuery;import org.apache.lucene.search.spans.SpanTermQuery;import org.apache.lucene.store.*;import org.junit.Test;import org.wltea.analyzer.lucene.IKAnalyzer;import java.nio.file.Paths;//使用Termquery查询@Testpublic void testTermQuery() throws Exception {Directory directory = FSDirectory.open(new File("D:\\temp\\index").toPath());IndexReader indexReader = DirectoryReader.open(directory);IndexSearcher indexSearcher = new IndexSearcher(indexReader);//创建查询对象Query query = new TermQuery(new Term("content", "lucene"));//执行查询TopDocs topDocs = indexSearcher.search(query, 10);//共查询到的document个数System.out.println("查询结果总数量:" + topDocs.totalHits);//遍历查询结果for (ScoreDoc scoreDoc : topDocs.scoreDocs) {Document document = indexSearcher.doc(scoreDoc.doc);System.out.println(document.get("filename"));//System.out.println(document.get("content"));System.out.println(document.get("path"));System.out.println(document.get("size"));}//关闭indexreaderindexSearcher.getIndexReader().close();}
数值范围查询
通过 IntPoint, LongPoint, FloatPoint, DoublePoint 中的方法构建对应的查询。
@Testpublic void testRangeQuery() throws Exception {IndexSearcher indexSearcher = getIndexSearcher();Query query = LongPoint.newRangeQuery("size", 0l, 10000l);printResult(query, indexSearcher);}
Boolean查询
BooleanQuery,布尔查询,实现组合条件查询
@Testpublic void testSearchBooleanQuery() throws Exception {// 创建两个 TermQuery搜索对象Query query1 = new TermQuery(new Term("name", "lucene"));Query query2 = new TermQuery(new Term("desc", "java"));// 创建BooleanQuery搜索对象,组合查询条件BooleanQuery.Builder boolQuery = new BooleanQuery.Builder();// 组合条件,// 第一个参数,查询条件,第二个参数,组合方式boolQuery.add(query1, BooleanClause.Occur.MUST);boolQuery.add(query2, BooleanClause.Occur.MUST);doSearch(boolQuery.build());}
组合关系代表的意思如下:
1、MUST和MUST表示“与”的关系,即“交集”。
2、MUST和MUST_NOT前者包含后者不包含。
3、MUST_NOT和MUST_NOT没意义
4、SHOULD与MUST表示MUST,SHOULD失去意义;
5、SHOULD与MUST_NOT相当于MUST与MUST_NOT。 6、SHOULD与SHOULD表示“或”的关系,即“并集”。
短语查询
PhraseQuery phraseQuery = new PhraseQuery("desc","lucene");或者PhraseQuery phraseQuery = new PhraseQuery(3,"desc","lucene","java");
跨度查询
SpanTermQuery tq1 = new SpanTermQuery(new Term("desc", "lucene"));SpanTermQuery tq2 = new SpanTermQuery(new Term("desc", "java"));SpanNearQuery spanNearQuery = new SpanNearQuery(new SpanQuery[] { tq1, tq2 },4,true);
模糊查询
WildcardQuery:通配符查询, *表示0个或多个字符,?表示1个字符,\是转义符。通配符查询可能会 比较慢,不可以通配符开头(那样就是所有词项了)
WildcardQuery wildcardQuery = new WildcardQuery( new Term("name", "so*"));FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("name", "slors"), 2);
使用queryparser查询
可以对要查询的内容先分词,然后基于分词的结果进行查询
通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。
Query对象执行的查询语法可通过System.out.println(query);查询。
需要使用到分析器。建议创建索引时使用的分析器和查询索引时使用的分析器要一致。
查询语法
1、基础的查询语法,关键词查询:
域名+“:”+搜索的关键字
例如:name:java
2、范围查询
域名+“:”+[最小值 TO 最大值]
例如:size:[1 TO 1000]
注意:QueryParser不支持对数字范围的搜索,它支持字符串范围。数字范围搜索建议使用对应的 Point。
3、组合条件查询
第一种写法:
1)+条件1 + 条件2:两个条件之间是并且的关系and
例如:+filename:lucene + content:lucene
2)+条件1 条件2:必须满足第一个条件,应该满足第二个条件
例如:+filename:lucene content:lucene
3)条件1 条件2:两个条件满足其一即可。
例如:filename:lucene content:lucene
4)-条件1条件2:必须不满足条件1,要满足条件2
例如:-filename:lucene content:lucene
| 逻辑 | 实现 |
|---|---|
| Occur.MUST查询条件必须满足,相当于AND | +(加号) |
| Occur.SHOULD查询条件可选,相当于OR | 空(不用符号) |
| Occur.MUST_NOT查询条件不能满足,相当于NOT非 | -(减号) |
第二种写法:
条件1 AND 条件2
条件1 OR 条件2
条件1 NOT 条件2
QueryParser
public void testSearchIndex() throws Exception {// 创建分词器Analyzer analyzer = new StandardAnalyzer();// 1. 创建Query搜索对象// 创建搜索解析器,第一个参数:默认Field域,第二个参数:分词器QueryParser queryParser = new QueryParser("desc", analyzer);// 创建搜索对象Query query = queryParser.parse("desc:java AND name:lucene");// 打印生成的搜索语句System.out.println(query);// 执行搜索doSearch(query);}
MultiFieldQueryParser
@Testpublic void testSearchMultiFieldQueryParser() throws Exception {// 创建分词器Analyzer analyzer = new IKAnalyzer();// 1. 创建MultiFieldQueryParser搜索对象String[] fields = {"name", "desc"};MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(fields, analyzer);// 创建搜索对象Query query = multiFieldQueryParser.parse("lucene");// 打印生成的搜索语句System.out.println(query);// 执行搜索doSearch(query);}
生成的查询语句: name:lucene desc:lucene
StandardQueryParser
@Testpublic void testStandardQueryParser() throws Exception {Analyzer analyzer = new StandardAnalyzer();StandardQueryParser standardQueryParser = new StandardQueryParser(analyzer);//Query query = standardQueryParser.parse("desc:java AND name:lucene","desc");//Query query = standardQueryParser.parse("+desc:java + name:lucene","desc");// Query query = standardQueryParser.parse("desc:java name:lucene","desc");//Query query = standardQueryParser.parse("name:L*","desc");//Query query = standardQueryParser.parse("lucensess~","desc");//Query query = standardQueryParser.parse("name:[Ha TO mock]","desc");Query query = standardQueryParser.parse("\"lucene java\"~3", "desc");doSearch(query);}
StandardQueryParser 其它查询举例
//通配符匹配 建议通配符在后 通配符在前效率低query = parser.parse("name:L*","desc");query = parser.parse("name:L???","desc");//模糊匹配query = parser.parse("lucene~","desc");//区间查询query = parser.parse("id:[1 TO 100]","desc");//跨度查询 ~2表示词语之间包含两个词语query= parser.parse("\"lucene java\"~2","desc");
