Lucene:完全禁用加权,得分,排名,

时间:2014-03-30 13:59:15

标签: lucene

我正在使用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需要花费很多时间。现在,我不需要对我的结果进行任何评分或排名,因为我只对绝对文档感兴趣。

是否有一种方便的方法(例如预先存在的类)来完全禁用评分和加权?如果没有,是否有任何提示我需要为我的用例扩展哪些类?

2 个答案:

答案 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