我正在使用Lucene构建令牌共同出现的大索引(例如[elephant,animal]
,[melon,fruit]
,[bmw,car]
,...)。我使用BooleanQuery
查询共同出现的索引以获得绝对计数,这两个令牌在我的索引中共同出现的频率如下:
// search for documents which contain word+category
BooleanQuery query = new BooleanQuery();
query.add(new TermQuery(new Term("word", word)), Occur.MUST);
query.add(new TermQuery(new Term("category", category)), Occur.MUST);
// only care about the total number of hits
TotalHitCountCollector collector = new TotalHitCountCollector();
searcher.search(query, collector);
int count = collector.getTotalHits();
这些查询运行频繁,我目前对性能不满意。我发现,方法BooleanQuery#createWeight
需要花费很多时间。现在,我不需要对我的结果进行任何评分或排名,因为我只对绝对文档感兴趣。
是否有一种方便的方法(例如预先存在的类)来完全禁用评分和加权?如果没有,是否有任何提示我需要为我的用例扩展哪些类?
答案 0 :(得分:4)
我不太确定它是否会以这样的方式绕过评分,以便获得您正在寻找的性能提升,但是应用常量分数的简单方法是将查询包装在{{ 3}},如:
BooleanQuery bq = new BooleanQuery();
//etc.
ConstantScoreQuery query = new ConstantScoreQuery(bq);
searcher.search(query, collector);
但是,强烈建议使用Filter
s。过滤器不仅可以绕过分数,还可以缓存结果,因此您可以使用"类别"特别是,这个领域似乎是一个非常好的地方。第一次使用过滤器在类别中查询时,需要更长时间来构建该过滤器的缓存,但在此之后,您应该看到速度的显着提高。看看ConstantScoreQuery
。
像:
Query query = new TermQuery(new Term("word", word));
Filter filter = new FieldCacheTermsFilter("category", category);
TotalHitCountCollector collector = new TotalHitCountCollector();
searcher.search(query, filter, collector);
int count = collector.getTotalHits();
答案 1 :(得分:1)
我遇到了类似的问题,并提出了与Lucene 7兼容的解决方案。(不幸的是,FieldCacheTermsFilter类和接受过滤器的搜索方法在Lucene 7中不可用)。
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.SimpleCollector;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class UnscoredCollector extends SimpleCollector {
private final List<Integer> docIds = new ArrayList<>();
private LeafReaderContext currentLeafReaderContext;
@Override
protected void doSetNextReader(LeafReaderContext context) throws IOException {
this.currentLeafReaderContext = context;
}
@Override
public boolean needsScores(){
return false;
}
@Override
public void collect(int localDocId) {
docIds.add(currentLeafReaderContext.docBase + localDocId);
}
}
...然后在搜索时使用了收集器
UnscoredCollector collector = new UnscoredCollector();
indexSearcher.search(query, collector);
//docId's are now available in the docIds ArrayList in the UnscoredCollector