简介

对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。

可通过两种方法创建查询对象:

  1. 使用Lucene提供Query子类

Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,WildcardQuery 统配查询 各种Point的数字范围查询等。
image.png

  1. 使用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号等。

指定要查询的域和要查询的关键词。

  1. import org.apache.lucene.analysis.Analyzer;
  2. import org.apache.lucene.analysis.standard.StandardAnalyzer;
  3. import org.apache.lucene.document.Document;
  4. import org.apache.lucene.document.IntPoint;
  5. import org.apache.lucene.index.DirectoryReader;
  6. import org.apache.lucene.index.IndexReader;
  7. import org.apache.lucene.index.Term;
  8. import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
  9. import org.apache.lucene.queryparser.classic.QueryParser;
  10. import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser;
  11. import org.apache.lucene.search.*;
  12. import org.apache.lucene.search.spans.SpanNearQuery;
  13. import org.apache.lucene.search.spans.SpanQuery;
  14. import org.apache.lucene.search.spans.SpanTermQuery;
  15. import org.apache.lucene.store.*;
  16. import org.junit.Test;
  17. import org.wltea.analyzer.lucene.IKAnalyzer;
  18. import java.nio.file.Paths;
  19. //使用Termquery查询
  20. @Test
  21. public void testTermQuery() throws Exception {
  22. Directory directory = FSDirectory.open(new File("D:\\temp\\index").toPath());
  23. IndexReader indexReader = DirectoryReader.open(directory);
  24. IndexSearcher indexSearcher = new IndexSearcher(indexReader);
  25. //创建查询对象
  26. Query query = new TermQuery(new Term("content", "lucene"));
  27. //执行查询
  28. TopDocs topDocs = indexSearcher.search(query, 10);
  29. //共查询到的document个数
  30. System.out.println("查询结果总数量:" + topDocs.totalHits);
  31. //遍历查询结果
  32. for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
  33. Document document = indexSearcher.doc(scoreDoc.doc);
  34. System.out.println(document.get("filename"));
  35. //System.out.println(document.get("content"));
  36. System.out.println(document.get("path"));
  37. System.out.println(document.get("size"));
  38. }
  39. //关闭indexreader
  40. indexSearcher.getIndexReader().close();
  41. }

数值范围查询

通过 IntPoint, LongPoint, FloatPoint, DoublePoint 中的方法构建对应的查询。

  1. @Test
  2. public void testRangeQuery() throws Exception {
  3. IndexSearcher indexSearcher = getIndexSearcher();
  4. Query query = LongPoint.newRangeQuery("size", 0l, 10000l);
  5. printResult(query, indexSearcher);
  6. }

Boolean查询

BooleanQuery,布尔查询,实现组合条件查询

  1. @Test
  2. public void testSearchBooleanQuery() throws Exception {
  3. // 创建两个 TermQuery搜索对象
  4. Query query1 = new TermQuery(new Term("name", "lucene"));
  5. Query query2 = new TermQuery(new Term("desc", "java"));
  6. // 创建BooleanQuery搜索对象,组合查询条件
  7. BooleanQuery.Builder boolQuery = new BooleanQuery.Builder();
  8. // 组合条件,
  9. // 第一个参数,查询条件,第二个参数,组合方式
  10. boolQuery.add(query1, BooleanClause.Occur.MUST);
  11. boolQuery.add(query2, BooleanClause.Occur.MUST);
  12. doSearch(boolQuery.build());
  13. }

组合关系代表的意思如下:
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表示“或”的关系,即“并集”。

短语查询

  1. PhraseQuery phraseQuery = new PhraseQuery("desc","lucene");
  2. 或者
  3. PhraseQuery phraseQuery = new PhraseQuery(3,"desc","lucene","java");

跨度查询

  1. SpanTermQuery tq1 = new SpanTermQuery(new Term("desc", "lucene"));
  2. SpanTermQuery tq2 = new SpanTermQuery(new Term("desc", "java"));
  3. SpanNearQuery spanNearQuery = new SpanNearQuery(new SpanQuery[] { tq1, tq2 },4,true);

模糊查询

WildcardQuery:通配符查询, *表示0个或多个字符,?表示1个字符,\是转义符。通配符查询可能会 比较慢,不可以通配符开头(那样就是所有词项了)

  1. WildcardQuery wildcardQuery = new WildcardQuery( new Term("name", "so*"));
  2. 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

  1. public void testSearchIndex() throws Exception {
  2. // 创建分词器
  3. Analyzer analyzer = new StandardAnalyzer();
  4. // 1. 创建Query搜索对象
  5. // 创建搜索解析器,第一个参数:默认Field域,第二个参数:分词器
  6. QueryParser queryParser = new QueryParser("desc", analyzer);
  7. // 创建搜索对象
  8. Query query = queryParser.parse("desc:java AND name:lucene");
  9. // 打印生成的搜索语句
  10. System.out.println(query);
  11. // 执行搜索
  12. doSearch(query);
  13. }


MultiFieldQueryParser

  1. @Test
  2. public void testSearchMultiFieldQueryParser() throws Exception {
  3. // 创建分词器
  4. Analyzer analyzer = new IKAnalyzer();
  5. // 1. 创建MultiFieldQueryParser搜索对象
  6. String[] fields = {"name", "desc"};
  7. MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(fields, analyzer);
  8. // 创建搜索对象
  9. Query query = multiFieldQueryParser.parse("lucene");
  10. // 打印生成的搜索语句
  11. System.out.println(query);
  12. // 执行搜索
  13. doSearch(query);
  14. }

生成的查询语句: name:lucene desc:lucene

StandardQueryParser

  1. @Test
  2. public void testStandardQueryParser() throws Exception {
  3. Analyzer analyzer = new StandardAnalyzer();
  4. StandardQueryParser standardQueryParser = new StandardQueryParser(analyzer);
  5. //Query query = standardQueryParser.parse("desc:java AND name:lucene","desc");
  6. //Query query = standardQueryParser.parse("+desc:java + name:lucene","desc");
  7. // Query query = standardQueryParser.parse("desc:java name:lucene","desc");
  8. //Query query = standardQueryParser.parse("name:L*","desc");
  9. //Query query = standardQueryParser.parse("lucensess~","desc");
  10. //Query query = standardQueryParser.parse("name:[Ha TO mock]","desc");
  11. Query query = standardQueryParser.parse("\"lucene java\"~3", "desc");
  12. doSearch(query);
  13. }

StandardQueryParser 其它查询举例

  1. //通配符匹配 建议通配符在后 通配符在前效率低
  2. query = parser.parse("name:L*","desc");
  3. query = parser.parse("name:L???","desc");
  4. //模糊匹配
  5. query = parser.parse("lucene~","desc");
  6. //区间查询
  7. query = parser.parse("id:[1 TO 100]","desc");
  8. //跨度查询 ~2表示词语之间包含两个词语
  9. query= parser.parse("\"lucene java\"~2","desc");