最近研究Lucene,找排序功能没有找到,所以撸了一下源码,下面开始介绍Lucene排序使用
一、全文搜索,多条件、排序功能点核心代码
// 排序字段信息
Sort sort = new Sort();
SortField[] sortFields = new SortField[1];
sort.setSort(sortFields);
TopFieldCollector topFieldCollector = TopFieldCollector.create(sort, pageNum + pageSize, Integer.MAX_VALUE);
// 这个地方query 可以直接是org.apache.lucene.search.Query及其子类。
indexSource.getIndexSearcher().search(query, collector);
// 解析,获取值信息
int totalHits = collector.getTotalHits();
ScoreDoc[] scoreDocs = collector.topDocs(pageNum, pageSize).scoreDocs;
// 获取到文档,按照传入参数信息转换即可
List<Document> documents = new ArrayList(scoreDocs.length);
for (int i = 0, size = scoreDocs.length; i < size; i++) {
Document document = getDocument(scoreDocs[i].doc);
documents.add(document);
}
核心代码有了,那么sortField怎么使用呢
二、sortField使用
本文主要描述两个构造方法的使用
// field 字段名称, Type 排序类型
public SortField(String field, Type type) {
initFieldType(field, type);
}
// field 字段名称, Type 排序类型, reverse 是否反转
public SortField(String field, Type type, boolean reverse) {
initFieldType(field, type);
this.reverse = reverse;
}
核心的问题点,就是字段我都知道,type是什么意思……
type类型如下
public static enum Type {
SCORE,
DOC,
STRING,
INT,
FLOAT,
LONG,
DOUBLE,
CUSTOM,
STRING_VAL,
REWRITEABLE
}
SCORE : 按文档分数(相关性)排序。排序值是浮点数,更高的值在前面
DOC:按文件编号排序(索引顺序)。排序值是整数,较低的值在前面
STRING:对于字符串,使用字符串名字的数量来为字符串排序。较低的值在前面(这个感觉有点问题)
INT:int 值进行排序,较低值在前面
FLOAT:float值进行排序,较低值在前面;
LONG:long值进行排序,较低值在前面
DOUBLE:double值进行排序,较低值在前面
CUSTOM:使用自定义比较器进行排序。排序值是任何可比较的,并且根据自然顺序进行排序
三、错误解决unexpected docvalues type NONE for field 'text' (expected=SORTED). Re-index with correct docvalues type.
要使用sort功能,需要在新建索引的时候指定排序字段
如下:
// 获取字段的值
int intFieldValue = jsonObject.getIntValue(fieldName);
add(new TextField(fieldName, String.valueOf(intFieldValue),org.apache.lucene.document.Field.Store.YES));
// 新增排序字段
add(new StoredField(fieldName, intFieldValue));
排序字段的使用类型及方法可以参考一下截图

四、关于模糊查询不准确问题
使用自带的分词器: WhitespaceAnalyzer
PerFieldAnalyzerWrapper analyzer = new PerFieldAnalyzerWrapper(new WhitespaceAnalyzer());
// 使用两个星号来处理模糊匹配
String shouldValue = new StringBuilder("").append(value).append("").toString();
// 封装term请求参数信息功能点
Term term = new Term(fieldName, shouldValue);
使用BooleanQuery 已经 WildcardQuery 来通过正则表达式模糊查询
BooleanQuery.Builder shouldBuilder = new BooleanQuery.Builder();
shouldBuilder.add(new WildcardQuery(term), BooleanClause.Occur.SHOULD)
五、多条件查询、鉴权查询
当我们使用Lucene查询是,经常需要进行各种查询条件结合使用,比如:必须相等,不等、包含于等
如下代码所示,可以封装所有非模糊查询到一个 booleanQuery
// 定义一个BooleanQuery
BooleanQuery.Builder mustBuilder = new BooleanQuery.Builder();
//mustTermList 表示所有必须相等的 term 的 list集合
if (CollUtil.isNotEmpty(mustTermList)) {
mustTermList.forEach(a -> mustBuilder.add(new TermQuery(a), BooleanClause.Occur.MUST));
}
// notInTermList 类似于mysql not in 也是一个 term的list
if (CollUtil.isNotEmpty(notInTermList)) {
for (Term[] terms : notInTermList) {
MultiPhraseQuery.Builder multiBuilder = new MultiPhraseQuery.Builder();
multiBuilder.add(terms);
mustBuilder.add(multiBuilder.build(), BooleanClause.Occur.MUST_NOT);
}
}
// mustNotTermList 表示所有不等于 的Term 的列表
if (CollUtil.isNotEmpty(mustNotTermList)) {
mustNotTermList.forEach(a -> mustBuilder.add(new TermQuery(a), BooleanClause.Occur.MUST_NOT));
}
// inTermList 表示所有 in 条件查询的LIST 列表
if (CollUtil.isNotEmpty(inTermList)) {
for (Term[] terms : inTermList) {
MultiPhraseQuery.Builder multiBuilder = new MultiPhraseQuery.Builder();
multiBuilder.add(terms);
mustBuilder.add(multiBuilder.build(), BooleanClause.Occur.MUST);
}
}
上面已经封装好了所有必要(必须相当、必须不等、包含、不包含等相关条件),那么下面就再封装模糊查询字段信息即可;
builder.add(booleanQuery, BooleanClause.Occur.MUST);
builder.add(clauses, BooleanClause.Occur.MUST);
这两段代码 其实就是求的两个查询结果集的交集
private static BooleanQuery getBooleanQuery(List<Term> shouldTermList, BooleanQuery.Builder mustBuilder) {
BooleanQuery.Builder shouldBuilder = new BooleanQuery.Builder();
// shouldTermList 表示所有模糊查询的 Term list 集合列表信息 下面代码表示将模糊查询封装到一个 BooleanQuery
if (CollUtil.isNotEmpty(shouldTermList)) {
shouldTermList.forEach(a -> shouldBuilder.add(new WildcardQuery(a), BooleanClause.Occur.SHOULD));
}
// 重新定义一个 BooleanQuery 这个 BooleanQuery 将会包含 必须查询条件和模糊查询条件的代码
BooleanQuery.Builder builder = new BooleanQuery.Builder();
BooleanQuery booleanQuery = mustBuilder.build();
if (booleanQuery.clauses().size() != 0) {
builder.add(booleanQuery, BooleanClause.Occur.MUST);
}
// 此处表示 模糊查询query
BooleanQuery clauses = shouldBuilder.build();
if (clauses.clauses().size() != 0) {
builder.add(clauses, BooleanClause.Occur.MUST);
}
return builder.build();
}
网友评论