4

インデックス作成には Lucene.net を使用しています。インデックスを作成するフィールドの 1 つは、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  

他の数値フィールドでも同じパターンが見られます。

未知の値はどこから来るのか?

4

1 に答える 1

4

NumericField は、トライ構造を使用してインデックス付けされます。表示される用語はその一部ですが、クエリを実行しても結果は返されません。

NumericField のインデックスを Int32.MaxValue の精度ステップで試してみると、値がなくなります。

数値フィールドのドキュメント

... Lucene 内では、各数値はトライ構造としてインデックス付けされ、各用語は、より大きな事前定義された大括弧 (単純に値の低精度表現) に論理的に割り当てられます。連続するブラケット間のステップ サイズは、precisionStep と呼ばれ、ビット単位で測定されます。precisionStep の値を小さくすると、括弧の数が多くなり、インデックスでより多くのディスク領域を消費しますが、範囲検索のパフォーマンスが向上する可能性があります。デフォルト値の 4 は、ディスク容量の消費とパフォーマンスの合理的なトレードオフのために選択されました。値を変更したい場合は、エキスパート コンストラクタ NumericField(String,int,Field.Store,boolean) を使用できます。NumericRangeQuery または NumericRangeFilter を作成するときは、合同値も指定する必要があることに注意してください。カーディナリティの低いフィールドの場合、より大きな精度のステップが適しています。カーディナリティが 100 未満の場合は、値ごとに 1 つの項を生成する Integer.MAX_VALUE を使用するのが適切です。...

NumericRangeQuery ドキュメントで利用可能な精度ステップの詳細:

precisionStep の適切な値は、使用法とデータ型によって異なります。

• すべてのデータ型のデフォルトは 4 で、precisionStep が指定されていない場合に使用されます。

• ほとんどの場合、64 ビット データ型 (long、double) の理想値は 6 または 8 です。

• ほとんどの場合、32 ビット データ型 (int、float) の理想値は 4 です。

• カーディナリティの低いフィールドの場合は、より大きな精度ステップが適しています。カーディナリティが 100 未満の場合は、•Integer.MAX_VALUE を使用するのが適切です (以下を参照)。

• long/double のステップが 64 以上、int/float のステップが 32 以上の場合、インデックス内の値ごとに 1 つのトークンが生成され、クエリは従来の TermRangeQuery と同じくらい遅くなります。ただし、並べ替えのみに使用されるフィールドを生成するために使用できます (この場合は、単純に Integer.MAX_VALUE を precisionStep として使用します)。フィールド キャッシュの構築は、テキストのみの数値よりもはるかに高速であるため、並べ替えに NumericFields を使用するのが理想的です。これらのフィールドには、値ごとに 1 つの用語があるため、個別のリストを作成するための用語の列挙にも使用できます (たとえば、ファセット / 検索する事前に選択された値)。上記の precisionSteps のいずれかを使用して、範囲クエリ最適化フィールドで並べ替えも可能です。

編集

少しのサンプルですが、これによって生成されたインデックスは、ルークで値が 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();
于 2012-08-09T19:26:50.427 に答える