为什么这个Lucene Field Boost没有保留,或者故事还有更多内容?

时间:2014-05-27 02:14:50

标签: lucene

Lucene 4.8.1 - 我试图将其归结为一个非常小的例子,只是说明了这个问题。

下面我插入一个文件,其字段的增强值为0.75。然后我立即将该文档拉出来,提取字段并打印出来 - 提升显示1.0。

public static void main(String[] args) throws IOException, ParseException {

    // Put a document in with a field with a boost of 0.75
    Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_48);
    Directory directory = new RAMDirectory();
    IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_48, analyzer));

    Document doc = new Document();
    Field field = new Field("NAME", "VALUE", TextField.TYPE_STORED);
    field.setBoost(0.75f); // HERE'S THE CUSTOM BOOST //
    doc.add(field);
    writer.addDocument(doc);
    writer.close();


    // Find the field in the document and show it's boost
    Query query = new QueryParser(Version.LUCENE_48, "NAME", analyzer).parse("VALUE");

    IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(directory));

    ScoreDoc[] hits = searcher.search(query, null, 1000).scoreDocs;
    Document hitDoc = searcher.doc(hits[0].doc);

    IndexableField iField = hitDoc.getFields().get(0);

    // Expecting 0.75, but it shows 1.0
    System.out.println(iField.name() + " = " + iField.stringValue() + " (boost " + iField.boost() + ")");
}

现在根据http://lucene.apache.org/core/4_8_1/core/org/apache/lucene/index/IndexableField.htmlboost()方法应该在 index 时显示字段的提升值,但输出结果如下:

NAME = VALUE (boost 1.0)

我已经使用调试器进行了检查,在添加文档时,该字段的增强值为0.75。

捕获似乎是在索引时的单词,这与文档插入时间不同。

仔细检查表明,在存储在索引中之前,增强值会经过一些归一化回转。因此,该值在索引中确实可以是1.0 。有人可以确认我的理解是否正确吗?

真正的问题是当为具有不同提升值的相同字段存储多个值时会发生什么?

Field f;
f = new Field("NAME", "AAA", TextField.TYPE_STORED); f(0.25); doc.add(f);
f = new Field("NAME", "BBB", TextField.TYPE_STORED); f(0.35); doc.add(f);
f = new Field("NAME", "CCC", TextField.TYPE_STORED); f(0.45); doc.add(f);

我的测试表明他们仍然提出了1.0的提升值。

NAME = VALUE (boost 1.0)
NAME = AAA (boost 1.0)
NAME = BBB (boost 1.0)
NAME = CCC (boost 1.0)

也许提升是该领域的一部分而不是其各种价值......尝试另一个实验,看看不同的领域名称是否会影响提升:

Field f;
f = new Field("XXX", "AAA", TextField.TYPE_STORED); f(0.25); doc.add(f);
f = new Field("YYY", "BBB", TextField.TYPE_STORED); f(0.35); doc.add(f);
f = new Field("ZZZ", "CCC", TextField.TYPE_STORED); f(0.45); doc.add(f);

我的测试结果仍显示它们的推出值均为1.0。

NAME = VALUE (boost 1.0)
XXX = AAA (boost 1.0)
YYY = BBB (boost 1.0)
ZZZ = CCC (boost 1.0)

我也可以使用多个文档获得类似的结果。无论我做什么,我似乎总是得到1.0。

我错过了什么?

1 个答案:

答案 0 :(得分:2)

我相信你的提升正确存储,你无法从索引中检索提升。为了证明这一点,运行您的示例代码(感谢SSCCE!),我添加了行以吐出explain(该行为:System.out.println(searcher.explain(query, 0).toString());),我们得到:

0.23013961 = (MATCH) weight(NAME:value in 0) [DefaultSimilarity], result of:
  0.23013961 = fieldWeight in 0, product of:
    1.0 = tf(freq=1.0), with freq of:
      1.0 = termFreq=1.0
    0.30685282 = idf(docFreq=1, maxDocs=1)
    0.75 = fieldNorm(doc=0)

NAME = VALUE (boost 1.0)

您可以在fieldNorm

中的倒数第二行看到您的提升

这给出了一个模糊的暗示,说明为什么你无法从索引中获得提升。它存储在fieldNorm中。这意味着您的提升与lengthNorm组合,然后压缩为单个字节,然后与索引中的字段一起存储。由于它被压缩为一个字节,因此压缩非常有损(3个二进制数字的精度),并且无法将该值与lengthNorm分开。在这个例子中,这似乎并不重要,但是如果我将索引值改为“VALUE AND STUFF”,由于fieldNorm的影响,整体lengthNorm变为0.5。

此外,有关您尝试使用相同名称的三个不同字段进行测试的旁注:添加到同一文档的具有相同名称的字段将成为同一字段的一部分。以这种方式添加的所有提升的乘积将是最终提升(在这种情况下,0.039375)