前言
本文我们来对Lucene具体如何进行数据的搜索,进行详细的介绍。
环境准备
我们直接使用在上一篇文章中的应用代码案例。
因为索引和存储两者是分开的,对于某一个字段我们可以建立索引,但是不存储,我们依然可以对此字段进行搜索,但是因为我们没有存储,所以我们搜索出来的结果中不显示此字段的内容。
本文为了结果的展示明显,我们将“desc“属性进行索引并且存储。
搜索结果TopDocs类
Lucene搜索结果可通过TopDocs遍历,TopDocs类提供了少量的属性,如下:
方法或属性 | 说明 |
---|---|
totalHits | 匹配搜索条件的总记录数 |
scoreDocs | 顶部匹配记录 |
注意:
Search方法需要指定匹配记录数量n:search(query, n)
TopDocs.totalHits:是匹配索引库中所有记录的数量
TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参
数n
方式一 使用Lucene提供的Query子类
公共测试类:
public void doSearch(Query query)throws Exception{
// 创建Directory 流对象
Directory directory = FSDirectory.open(Paths.get("D:/lucene/index"));
// 创建IndexReader
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(indexReader);
// 获取TopDocs
TopDocs topDocs = searcher.search(query,10);
System.out.println("查询索引总条数:" + topDocs.totalHits);
ScoreDoc[] docs = topDocs.scoreDocs;
// 解析结果集
for (ScoreDoc scoreDoc : docs){
int docID = scoreDoc.doc;
Document document = searcher.doc(docID);
System.out.println("docID:"+docID);
System.out.println("bookId:"+document.get("id"));
System.out.println("name:"+document.get("name"));
System.out.println("price:"+document.get("price"));
System.out.println("desc:"+document.get("desc"));
}
indexReader.close();
}
TermQuery
简介
TermQuery词项查询,TermQuery不使用分词器,搜索关键词进行精确匹配Field域中的词,比如订单
号、分类ID号等。
测试
@Test
public void testSearchTermQuery()throws Exception{
// 创建TermQuery 搜索对象
Query query = new TermQuery(new Term("name","lucene"));
doSearch(query);
}
结果
查询索引总条数:1
docID:0
bookId:1
name:Lucene
price:100.45
desc:Lucene Core is a Java library providing powerful indexing and search features, as well as spellchecking, hit highlighting and advanced analysis/tokenization capabilities. The PyLucene sub project provides Python bindings for Lucene Core.
BooleanQuery
简介
BooleanQuery,布尔查询,实现组合条件查询。
组合关系代表的意思如下:
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表示“或”的关系,即“并集”。
测试
@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
docID:0
bookId:1
name:Lucene
price:100.45
desc:Lucene Core is a Java library providing powerful indexing and search features, as well as spellchecking, hit highlighting and advanced analysis/tokenization capabilities. The PyLucene sub project provides Python bindings for Lucene Core.
PhraseQuery
phraseQuery即短语查询,代码实例:
@Test
public void testSearchPhraseQuery()throws Exception{
PhraseQuery query = new PhraseQuery("name","lucene");
//跨三个词查询,比如这个是查lucene和Java中间跨了三个词之内的内容
// PhraseQuery query = new PhraseQuery(3,"desc","lucene","java");
doSearch(query);
}
结果:
查询索引总条数:1
docID:0
bookId:1
name:Lucene
price:100.45
desc:Lucene Core is a Java library providing powerful indexing and search features, as well as spellchecking, hit highlighting and advanced analysis/tokenization capabilities. The PyLucene sub project provides Python bindings for Lucene Core.
PhraseQuery query = new PhraseQuery(3,"desc","lucene","java");
这个短语查询会匹配到Lucene Core is a Java
。因为Lucene和Java中间间隔的单词是3个以内的。
跨度查询
跨度查询,如下所示查询的结果是“lucene”和“Java“两个词中间跨度为3以内的句子:
@Test
public void testSearchSpanNearQuery()throws Exception{
SpanTermQuery tq1 = new SpanTermQuery(new Term("desc", "lucene"));
SpanTermQuery tq2 = new SpanTermQuery(new Term("desc", "java"));
SpanNearQuery spanNearQuery = new SpanNearQuery(new SpanQuery[] { tq1, tq2 },3,true);
doSearch(spanNearQuery);
}
结果:
查询索引总条数:1
docID:0
bookId:1
name:Lucene
price:100.45
desc:Lucene Core is a Java library providing powerful indexing and search features, as well as spellchecking, hit highlighting and advanced analysis/tokenization capabilities. The PyLucene sub project provides Python bindings for Lucene Core.
模糊查询
WildcardQuery:通配符查询, *表示0个或多个字符,?表示1个字符,\是转义符。通配符查询可能会比较慢,不可以通配符开头(那样就是所有词项了)
示例:
@Test
public void testSearchLikeQuery()throws Exception{
WildcardQuery wildcardQuery = new WildcardQuery( new Term("name", "so??"));
doSearch(wildcardQuery);
// FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("name", "slorss"), 2);
// doSearch(fuzzyQuery);
}
结果:
查询索引总条数:1
docID:1
bookId:11
name:Solr
price:320.45
desc:Solr is highly scalable, providing fully fault tolerant distributed indexing, search and analytics. It exposes Lucene's features through easy to use JSON/HTTP interfaces or native clients for Java and other languages.
数值查询
通过 IntPoint, LongPoint, FloatPoint, DoublePoint 中的方法构建对应的查询。
示例:
Query pointRangeQuery = IntPoint.newRangeQuery("id", 1,11);
方式二 使用QueryParser进行搜索
查询语法
-
基础的查询语法,关键词查询:
域名+“:”+搜索的关键字
例如:name:java
-
范围查询
域名+“:”+[最小值 TO 最大值]
例如:size:[1 TO 1000]
注意:QueryParser不支持对数字范围的搜索,它支持字符串范围。数字范围搜索建议使用对应的
Point。 -
组合条件查询
第一种写法:
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
代码示例
@Test
public void testQueryPasrser() throws Exception{
Analyzer analyzer = new StandardAnalyzer();
QueryParser queryParser = new QueryParser("desc",analyzer);
// 构建搜索对象
Query query = queryParser.parse("desc:java AND name:lucene");
doSearch(query);
}
执行结果:
查询索引总条数:1
docID:0
bookId:1
name:Lucene
price:100.45
desc:Lucene Core is a Java library providing powerful indexing and search features, as well as spellchecking, hit highlighting and advanced analysis/tokenization capabilities. The PyLucene sub project provides Python bindings for Lucene Core.
源码
总结
本文主要对Lucene如何进行搜索做了详细的介绍,主要有使用Query子类和QueryParser进行搜索两种方式。
更多
更多我亲身经历的面试真题,还有想要内推大厂的小伙伴可以联系我,请关注微信公众号:【程序员资料站】,回复关键字 “面试” 获取更多面试资料,回复“内推”,我帮你内推大厂。