私はfieldNorm
、(インデックス時に)計算され、クエリ時にどのように使用されるか(そして明らかに再計算されるか)を理解しようとしています。
すべての例で、ストップワードなしでStandardAnalyzerを使用しています。
DefaultSimilarity
インデックスを作成しているときに'sメソッドを削除するcomputeNorm
と、2つの特定のドキュメントに対して次のように返されることに気付きました。
- ドキュメントAの場合は0.5(フィールドに4つのトークンがあります)
- ドキュメントBの場合は0.70710677(フィールドに2つのトークンがあります)
これは、次の式を使用して行います。
state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)));
ここで、ブーストは常に1です。
その後、これらのドキュメントをクエリすると、クエリの説明で次のようになります。
0.5 = fieldNorm(field=titre, doc=0)
ドキュメントAの場合0.625 = fieldNorm(field=titre, doc=1)
ドキュメントBの場合
これはすでに奇妙です(私にとって、何かが欠けているのは私だと確信しています)。インデックス時に計算された値と同じフィールドノルムの値を取得しないのはなぜですか?これは実際の「クエリの正規化」のことですか?もしそうなら、それはどのように機能しますか?
ただし、2つのクエリ時のfieldNormは、インデックス時に計算されたものと同じ順序になるため、これは多かれ少なかれ問題ありません(どちらの場合も、値が短いフィールドほどfieldNormが高くなります)。
次に、次のようにcomputeNormsメソッドを実装した独自のSimilarityクラスを作成しました。
public float computeNorm(String pField, FieldInvertState state) {
norm = (float) (state.getBoost() + (1.0d / Math.sqrt(state.getLength())));
return norm;
}
インデックス時に、次のようになります。
- ドキュメントAの場合は1.5(フィールドに4つのトークンがあります)
- ドキュメントBの場合は1.7071068(フィールドに2つのトークンがあります)
ただし、これらのドキュメントをクエリすると、explain関数によって報告されたものと同じフィールドノルムが両方にあることがわかります。
1.5 = fieldNorm(field=titre, doc=0)
ドキュメントAの場合1.5 = fieldNorm(field=titre, doc=1)
ドキュメントBの場合
私にとって、これは本当に奇妙なことです。インデックス時にfieldNormを計算するために明らかに良い類似性を使用すると、トークンの数に比例する適切な値が得られ、後でクエリ時にすべてが失われ、クエリは、両方のドキュメントが同じフィールドノルムを持っていると言いますか?
だから私の質問は:
- 類似性のcomputeNormメソッドによって報告されたインデックス時間fieldNormが、クエリの説明によって報告されたものと同じままにならないのはなぜですか?
- なぜ、インデックス時に(類似性computeNormを介して)取得された2つの異なるfieldNorm値に対して、クエリ時に同一のfieldNorm値を取得するのですか?
==更新
わかりました。Luceneのドキュメントで、私の質問の一部を明確にするものを見つけましたが、すべてではありません。
ただし、結果のノルム値は、保存される前に1バイトとしてエンコードされます。検索時に、ノルムバイト値がインデックスディレクトリから読み取られ、floatノルム値にデコードされます。このエンコード/デコードは、インデックスサイズを縮小しますが、精度が低下するという代償を伴います。decode(encode(x))=xであるとは限りません。たとえば、decode(encode(0.89))=0.75です。
どのくらいの精度の損失がありますか?精度損失の再計算後も値が異なるままになるように、異なる値の間に配置する必要のある最小のギャップはありますか?