java - Lucene CustomScoreQuery 不从 FunctionQuery 的 FieldSource 传递值

标签 java lucene

如果我从 Lucene Java Doc Page 理解正确的话,将 CustomScoreQuery 实例设置为 strict 应将 FunctionQueryFieldSource 值未经修改(如规范化)传递到方法 public float customScore(int doc, float subQueryScore, float valSrcScore)CustomScoreProvidervalSrcScore。 因此,我想,我准确地得到了存储在文档的 FloatSourceField 中的浮点值。

但是当索引数据量变大时,情况似乎并非如此。这里我有一个最小的例子来说明我的意思:

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.queries.*;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
import org.apache.lucene.search.*;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import java.io.IOException;
public class CustomScoreTest {
    public static void main(String[] args) throws IOException {
        RAMDirectory index = new RAMDirectory();
        IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, new StandardAnalyzer());
        IndexWriter writer = new IndexWriter(index, config);

        // prepare dummy text
        String text = "";
        for (int i = 0; i < 1000; i++) text += "abc ";

        // add dummy docs
        for (int i = 0; i <25000; i++) {
            Document doc = new Document();
            doc.add(new FloatField("number", i * 100f, Field.Store.YES));
            doc.add(new TextField("text", text, Field.Store.YES));
            writer.addDocument(doc);
        }
        writer.close();

        IndexReader reader = IndexReader.open(index);
        IndexSearcher searcher = new IndexSearcher(reader);

        Query q1 = new TermQuery(new Term("text", "abc"));
        CustomScoreQuery q2 = new CustomScoreQuery(q1, new FunctionQuery(new FloatFieldSource("number"))) {
            protected CustomScoreProvider getCustomScoreProvider(AtomicReaderContext ctx) throws IOException {
                return new CustomScoreProvider(ctx) {
                    public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
                        float diff = Math.abs(valSrcScore - searcher.doc(doc).getField("number").numericValue().floatValue());
                        if (diff > 0) throw new IllegalStateException("diff: " + diff);
                        return super.customScore(doc, subQueryScore, valSrcScore);
                    }
                };
            }
        };

        // In strict custom scoring, the part does not participate in weight normalization.
        // This may be useful when one wants full control over how scores are modified, and
        // does not care about normalising by the  part
        q2.setStrict(true);

        // Exception in thread "main" java.lang.IllegalStateException: diff: 1490700.0
        searcher.search(q2, 10);
    }
}

如本示例中所述,会抛出异常,因为 valSrcScore 与存储在文档“number”字段中的实际值有很大差异。

但是当我将索引虚拟文档的数量减少到(例如 2500)时,它会按预期工作,并且我得到的值与“number”字段中的值相差 0。

我在这里做错了什么?

最佳答案

您运行的是哪个版本的 lucene?一种可能性是,随着索引大小的增加,AtomicReaderContext 应该替换为 LeafReaderContext。只是一个假设

关于java - Lucene CustomScoreQuery 不从 FunctionQuery 的 FieldSource 传递值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28263382/

相关文章:

java - 关于Android中BitmapFactory.Options的问题

java - 特定单词之前的单词数

search - Lucene 评分结果

Solr - 在文档中重复查询中的单词没有额外分数

solr - Apache Solr 索引和过滤查询

solr - 如何为 Lucene 4.0 启用新的可选 BlockPostingsFormat?

java - MyBatis 插入列表值

java - 在单独的线程中更新 BufferedImage 的单独区域安全吗?

java - 如何根据登录的用户设置可见的 JButton?

search - Elasticsearch 区分模糊结果