简介
对要搜索的信息创建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查询
@Test
public 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"));
}
//关闭indexreader
indexSearcher.getIndexReader().close();
}
数值范围查询
通过 IntPoint, LongPoint, FloatPoint, DoublePoint 中的方法构建对应的查询。
@Test
public void testRangeQuery() throws Exception {
IndexSearcher indexSearcher = getIndexSearcher();
Query query = LongPoint.newRangeQuery("size", 0l, 10000l);
printResult(query, indexSearcher);
}
Boolean查询
BooleanQuery,布尔查询,实现组合条件查询
@Test
public 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
@Test
public 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
@Test
public 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");