NumericFields 使用trie 结构进行索引。您看到的术语是其中的一部分,但如果您查询它们,则不会返回结果。
尝试使用 Int32.MaxValue 的精度步长为 NumericField 建立索引,这些值将消失。
NumericField documentation
... 在 Lucene 中,每个数值都被索引为一个 trie 结构,其中每个术语在逻辑上被分配到越来越大的预定义括号(它们只是值的低精度表示)。每个连续括号之间的步长称为precisionStep,以位为单位。较小的precisionStep 值会导致更多的括号,这会在索引中消耗更多的磁盘空间,但可能会导致更快的范围搜索性能。选择默认值 4 是为了合理权衡磁盘空间消耗与性能。如果您想更改值,可以使用专家构造函数 NumericField(String,int,Field.Store,boolean)。请注意,您还必须在创建 NumericRangeQuery 或 NumericRangeFilter 时指定一个全等值。对于低基数场,较大的精度步长是好的。如果基数
NumericRangeQuery documentation 中提供有关精度步长的更多详细信息:
precisionStep 的正确值取决于使用情况和数据类型:
• 所有数据类型的默认值为 4,当没有
给出了precisionStep。
• 大多数情况下 64 位数据的理想值
types (long, double) 是 6 或 8。
• 大多数情况下 32 位的理想值
数据类型 (int, float) 为 4。
• 对于较大的低基数字段
精确的步骤是好的。如果基数
• 对于 long/double 和 Steps ≥64
≥32 for int/float 为索引中的每个值生成一个标记,并且
查询与传统的 TermRangeQuery 一样慢。但它可以
用于生成仅用于排序的字段(在这种情况下
只需使用 Integer.MAX_VALUE 作为precisionStep)。使用数值字段
排序是理想的,因为构建字段缓存要快得多
而不是纯文本数字。这些字段的每个值都有一个术语,并且
因此也可以使用术语枚举来构建不同的列表
(例如要搜索的构面/预选值)。排序也是
可以使用上述方法之一使用范围查询优化字段
精确步数。
编辑
小样本,由此生成的索引将在 luke 中显示值为 8192、9984、1792 等的术语,但使用将它们包含在查询中的范围不会产生结果:
NumericField number = new NumericField("number", Field.Store.YES, true);
Field regular = new Field("normal", "", Field.Store.YES, Field.Index.ANALYZED);
IndexWriter iw = new IndexWriter(FSDirectory.GetDirectory("C:\\temp\\testnum"), new StandardAnalyzer(), true);
Document doc = new Document();
doc.Add(number);
doc.Add(regular);
number.SetIntValue(1);
regular.SetValue("one");
iw.AddDocument(doc);
number.SetIntValue(2);
regular.SetValue("one");
iw.AddDocument(doc);
number.SetIntValue(13);
regular.SetValue("one");
iw.AddDocument(doc);
number.SetIntValue(2000);
regular.SetValue("one");
iw.AddDocument(doc);
number.SetIntValue(9999);
regular.SetValue("one");
iw.AddDocument(doc);
iw.Commit();
IndexSearcher searcher = new IndexSearcher(iw.GetReader());
NumericRangeQuery rangeQ = NumericRangeQuery.NewIntRange("number", 1, 2, true, true);
var docs = searcher.Search(rangeQ);
Console.WriteLine(docs.Length().ToString()); // prints 2
rangeQ = NumericRangeQuery.NewIntRange("number", 13, 13, true, true);
docs = searcher.Search(rangeQ);
Console.WriteLine(docs.Length().ToString()); // prints 1
rangeQ = NumericRangeQuery.NewIntRange("number", 9000, 9998, true, true);
docs = searcher.Search(rangeQ);
Console.WriteLine(docs.Length().ToString()); // prints 0
Console.ReadLine();