Elasticsearch で ngram フィルターを使用すると、「test」などを検索すると、ドキュメント「latest」、「tests」、および「test」が返されます。「クエリ「test」に完全に一致するドキュメントが常に検索結果の上位に返されるようにする方法はありますか?
3 に答える
これは ngram のちょっとした問題です。ランキングで多くの誤検出が発生します。解決策は、ngram とシングルを組み合わせることです。基本的に、ngram に加えて、完全な単語を個別の用語または単語の組み合わせとしてインデックス付けすることもできます。シングルは基本的に ngram に似ていますが、文字ではなく単語を使用します。
そうすれば、シングル タームに対する完全一致は、ngram のみに一致するものよりもスコアが高くなります。
更新します。カスタム アナライザーの例を次に示します。定義したら、マッピングで使用できます。この場合、icu_normalizer と折りたたみと、suggestions_shingle を使用します。これはすべてデフォルトのアナライザーとして設定されているため、すべての文字列がこの方法で処理されます。
{
"analyzer":{
"default":{
"tokenizer":"icu_tokenizer",
"filter":"icu_normalizer,icu_folding,suggestions_shingle"
}
},
"filter": {
"suggestions_shingle": {
"type": "shingle",
"min_shingle_size": 2,
"max_shingle_size": 5
}
}
}
multifield および multimatch クエリが必要です。
同様の問題があります。ファースト ネームで検索する必要があったので、「And」という検索語を入力すると、最初に「Andy」が表示され、次に「Mandy」が表示されます。nGram だけでは、それを達成できませんでした。
フロント edgeNGram を使用するアナライザーをもう 1 つ追加しました (以下のコードは Spring Data Elasticsearch 用ですが、アイデアを得ることができます)。
setting.put("analysis.analyzer.word_parts.type", "custom");
setting.put("analysis.analyzer.word_parts.tokenizer", "ngram_tokenizer");
setting.put("analysis.analyzer.word_parts.filter", "lowercase");
setting.put("analysis.analyzer.type_ahead.type", "custom");
setting.put("analysis.analyzer.type_ahead.tokenizer", "edge_ngram_tokenizer");
setting.put("analysis.analyzer.type_ahead.filter", "lowercase");
setting.put("analysis.tokenizer.ngram_tokenizer.type", "nGram");
setting.put("analysis.tokenizer.ngram_tokenizer.min_gram", "3");
setting.put("analysis.tokenizer.ngram_tokenizer.max_gram", "50");
setting.put("analysis.tokenizer.ngram_tokenizer.token_chars", new String[] { "letter", "digit" });
setting.put("analysis.tokenizer.edge_ngram_tokenizer.type", "edgeNGram");
setting.put("analysis.tokenizer.edge_ngram_tokenizer.min_gram", "2");
setting.put("analysis.tokenizer.edge_ngram_tokenizer.max_gram", "20");
必須フィールドを複数フィールドとしてマッピングしました。
@MultiField(mainField = @Field(type = FieldType.String, indexAnalyzer = "word_parts", searchAnalyzer = "standard"),
otherFields = @NestedField(dotSuffix = "autoComplete", type = FieldType.String, searchAnalyzer = "standard", indexAnalyzer = "type_ahead"))
private String firstName;
マルチマッチを使用しているクエリでは、最初に「firstName.autoComplete」を指定し、「firstName」だけではありませんでした
QueryBuilders.multiMatchQuery(searchTerm, new String[]{"firstName.autoComplete", "firstName"})
これは正常に動作しているようです。
あなたの場合、完全一致が必要な場合は、おそらく「edgeNGram」の代わりに「標準」を使用できます。