我们使用Lucene.net进行索引。我们索引的字段之一是数值字段,值为1到6,未设置为9999。
使用Luke浏览索引时,我们会看到无法识别的字词。该索引共包含38673个文档,Luke显示了该字段的以下排名最高的术语:
Term | Rank | Field | Text | Text (decoded as numeric-int)
1 | 38673 | Axis | x | 0
2 | 38673 | Axis | p | 0
3 | 38673 | Axis | t | 0
4 | 38673 | Axis | | | 0
5 | 19421 | Axis | l | 0
6 | 19421 | Axis | h | 0
7 | 19421 | Axis | d@ | 0
8 | 19252 | Axis | ` N | 9999
9 | 19252 | Axis | l | 8192
10 | 19252 | Axis | h ' | 9984
11 | 19252 | Axis | d@ p | 9984
12 | 18209 | Axis | ` | 4
13 | 950 | Axis | ` | 1
14 | 116 | Axis | ` | 5
15 | 102 | Axis | ` | 6
16 | 26 | Axis | ` | 3
17 | 18 | Axis | ` | 2
我们发现其他数字字段的模式相同。
未知值来自何处?
答案 0 :(得分:4)
NumericFields使用trie结构编制索引。您看到的术语是其中的一部分,但如果您查询它们,则不会返回结果。
尝试使用精确的Int32.MaxValue步骤索引NumericField,值将消失。
...在Lucene中,每个数值都被索引为trie结构,其中每个术语在逻辑上分配给越来越大的预定义括号(这只是值的低精度表示)。每个连续括号之间的步长称为precisionStep,以位为单位。较小的precisionStep值会导致更多的括号,这会占用索引中更多的磁盘空间,但可能会导致更快的范围搜索性能。选择默认值4以进行磁盘空间消耗与性能的合理权衡。如果要更改值,可以使用专家构造函数NumericField(String,int,Field.Store,boolean)。请注意,在创建NumericRangeQuery或NumericRangeFilter时,还必须指定一致值。对于低基数字段,较大的精度步长是好的。如果基数是< 100,使用Integer.MAX_VALUE是公平的,每个值产生一个项。 ...
NumericRangeQuery documentation中提供的有关精确步骤的更多详细信息:
precisionStep的良好值取决于用法和数据类型:
•所有数据类型的默认值为4,否则使用 给出precisionStep。
•大多数情况下64位数据的理想值 类型(长,双)是6或8.
•大多数情况下32位的理想值 数据类型(int,float)是4.
•对于较低的基数字段较大 精确的步骤是好的。如果基数是< 100,使用•Integer.MAX_VALUE(见下文)是公平的。
•长/双和≥64步 对于int / float,≥32会在索引中为每个值生成一个标记 查询与传统的TermRangeQuery一样慢。但它可以 用于生成仅用于排序的字段(在这种情况下) 只需使用Integer.MAX_VALUE作为precisionStep)。使用NumericFields 排序是理想的,因为构建字段缓存要快得多 而不是纯文字数字。这些字段每个值有一个术语 因此也可以使用术语枚举来构建不同的列表 (例如,要搜索的构面/预选值)。排序也是 使用以上之一可以使用范围查询优化字段 precisionSteps。
修改强>
小样本,由此产生的索引将在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();