Luke揭示了索引中数字字段的未知术语值

时间:2012-08-09 12:05:11

标签: lucene lucene.net luke

我们使用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  

我们发现其他数字字段的模式相同。

未知值来自何处?

1 个答案:

答案 0 :(得分:4)

NumericFields使用trie结构编制索引。您看到的术语是其中的一部分,但如果您查询它们,则不会返回结果。

尝试使用精确的Int32.MaxValue步骤索引NumericField,值将消失。

NumericField documentation

  

...在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();