Lucene查询结果对于long和double值不正确

时间:2017-11-03 12:38:51

标签: lucene double long-integer

我使用Lucene 6.1.0来索引具有名称和值的元素。
E.g。

<documents>
    <Document>
        <field name="NAME" value="Long_-1"/>
        <field name="VALUE" value="-1"/>
    </Document>
    <Document>
        <field name="NAME" value="Double_-1.0"/>
        <field name="VALUE" value="-1.0"/>
    </Document>
    <Document>
        <field name="NAME" value="Double_-0.5"/>
        <field name="VALUE" value="-0.5"/>
    </Document>
    <Document>
        <field name="NAME" value="Long_0"/>
        <field name="VALUE" value="0"/>
    </Document>
    <Document>
        <field name="NAME" value="Double_0.0"/>
        <field name="VALUE" value="0.0"/>
    </Document>
    <Document>
        <field name="NAME" value="Double_0.5"/>
        <field name="VALUE" value="0.5"/>
    </Document>
    <Document>
        <field name="NAME" value="Long_1"/>
        <field name="VALUE" value="1"/>
    </Document>
    <Document>
        <field name="NAME" value="Double_1.0"/>
        <field name="VALUE" value="1.0"/>
    </Document>
    <Document>
        <field name="NAME" value="Double_1.5"/>
        <field name="VALUE" value="1.5"/>
    </Document>
    <Document>
        <field name="NAME" value="Long_2"/>
        <field name="VALUE" value="2"/>
    </Document>
</documents>

根据文档,我使用LongPoint和DoublePoint来构建索引。

public static void addLongField(String name, long value, Document doc) {
    doc.add(new LongPoint(name, value));
    // since Lucene6.x a second field is required to store the values. 
    doc.add(new StoredField(name, value));
}

public static void addDoubleField(String name, double value, Document doc) {
    doc.add(new DoublePoint(name, value));
    // since Lucene6.x a second field is required to store the values. 
    doc.add(new StoredField(name, value));
}

由于我对长值和双值使用相同的字段,如果min和max值有不同的符号,我的RangeQuery会得到奇怪的结果。

LongPoint.newRangeQuery(field, minValue, maxValue);
DoublePoint.newRangeQuery(field, minValue, maxValue);

这个例子是正确的:
  VALUE:[1 TO 1] VALUE:[0.5 TO 1.0]

结果:
0.5 Double_0.5
1 Long_1
1.0 Double_1.0

这个例子是错误的   VALUE:[0 TO 1] VALUE:[ - 0.5 TO 1.0]

结果:
0 Long_0
0.0 Double_0.0
1 Long_1
-1 Long_-1
-0.5 Double_-0.5
0.5 Double_0.5
1.0 Double_1.0
2 Long_2

除了正确的结果外,还会返回所有长值。

有人知道为什么吗? 是否无法在同一字段中存储长值和双值? 非常感谢。

BR Tobias

1 个答案:

答案 0 :(得分:2)

不,您不应该在同一个字段中保留不同的数据类型。您应该将它们放在单独的字段中,或者将您的长片转换为双精度数(反之亦然),以便它们都以相同的格式编入索引。

要了解发生了什么,有助于了解数字字段的实际作用。数字字段以二进制表示形式编码,便于范围搜索该类型。整数类型的编码和浮点类型的编码是不可比的。例如,对于数字1:

  • long 1 = lucene BytesRef:[80 0 0 0 0 0 0 1]
  • double 1.0 = lucene BytesRef:[bf f0 0 0 0 0 0 0]

这些BytesRef二进制表示是实际被搜索的内容。由于查询的一部分是从-0.5到1.0的两倍,因此您实际上正在运行查询:

  • encodedvalue:[40 1f ff ff ff ff ff ff ff] - [bf f0 0 0 0 0 0 0]

在长值范围内不包含一些额外的点击数,但以外的大多数长值高低点(你&#39; d)需要进入Long.MAX_VALUE/2)附近。