【问题标题】:How does Lucene combine fields and boosting values to generate a score?Lucene 如何结合字段和提升值来生成分数?
【发布时间】:2014-02-06 18:13:55
【问题描述】:

我在此链接中关注了 Lucene 如何对文档进行评分:

https://lucene.apache.org/core/3_6_2/api/core/org/apache/lucene/search/Similarity.html

但是 Lucene 如何处理多个字段和字段提升?例如,如果我有两个字段:f1 和 f2 以及它们对应的字段提升:b1 和 b2,那么最终得分会是:

final score = b1*cosine_similarity(f1) + b2*cosine_similarity(f2)

提前致谢!

【问题讨论】:

    标签: boost lucene scoring


    【解决方案1】:

    余弦相似度是两个参数的函数。第一个是查询,第二个是文档。

    在您的情况下,您可能有一个布尔查询,其中包含这两个字段的子句。例如,“f1:文本或 f2:文本”。如果你看评分公式:

    score(q, d) = coord(q,d) * queryNorm(q) * sum[tf(t in d) * idf(t)^2 * t.getBoost() * norm(t,d)]
    

    你看到有一个元素 norm(t, d)。这个函数封装了提升和长度因子:

    norm(t,d) = doc.getBoost() * lengthNorm * prod[f.getBoost()]
    

    而那个f.getBoost()就是对应字段的boost。

    总而言之,它是上述查询的简化分数(假设两个术语的 tf = 1 和 idf = 1/2,并且除字段提升之外的所有提升都等于 1):

    score("f1: text OR f2: text", "{f1: '... text ...', f2: '... text ...'") = coordAndQueryNormPart * (1 * 1/4 * 1 * f1boost + 1 * 1/4 * 1 * f2boost) 
    

    更新:

    我写了一个可能有用的例子。这里的 Lucene 索引包含两个相等的文档,但是在第一个文档中“f1”字段被提升:

        Directory dir = new RAMDirectory();
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, new StandardAnalyzer(Version.LUCENE_36));
        IndexWriter writer = new IndexWriter(dir, config);
    
        float field1Boost = 2.0f;
    
        Document doc = new Document();
        Field f1 = new Field("f1", "field text", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
        f1.setBoost(field1Boost);
        doc.add(f1);
        doc.add(new Field("f2", "another text", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
        writer.addDocument(doc);
    
    
        doc = new Document();
        doc.add(new Field("f1", "field text", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
        doc.add(new Field("f2", "another text", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
        writer.addDocument(doc);
        writer.commit();
    
        writer.close();
    
        IndexReader indexReader = IndexReader.open(dir);
    
        IndexSearcher searcher = new IndexSearcher(indexReader);
        QueryParser parser = new QueryParser(Version.LUCENE_36, "f1", new StandardAnalyzer(Version.LUCENE_36));
        Query query = parser.parse("f1: text OR f2: text");
        TopDocs docs = searcher.search(query, 2);
    
        float score1 = docs.scoreDocs[0].score;
        float score2 = docs.scoreDocs[1].score;
    
        float score1check = 0.26274973154067993f * field1Boost + 0.26274973154067993f;
        float score2check = 0.26274973154067993f + 0.26274973154067993f;
    
        if (Math.abs(score1 - score1check) > 0.00001) throw new RuntimeException();
        if (Math.abs(score2 - score2check) > 0.00001) throw new RuntimeException();
    
        System.out.println("Score 1 = " + score1 + " ; score 2 = " + score2);  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-11
      • 2021-12-14
      • 2018-02-28
      • 1970-01-01
      • 2017-05-26
      • 2013-12-24
      • 2013-11-24
      • 1970-01-01
      相关资源
      最近更新 更多