検索と並べ替えの両方で、トークン化されたフィールドとトークン化されていないフィールドを最適に管理する方法を見つけるのに苦労しています。私たちの目標は非常に簡単です。
- 部分単語検索をサポート
- すべてのフィールドでソートをサポート
- マッピングは動的でなければならず、顧客は実行時に新しいフィールドを追加します。
これは動的テンプレートを使用して実現できます。デフォルトのトークナイザー、カスタムの ngram トークナイザー、および未分析のトークナイザーを使用して文字列を保存します。マッピング:
curl -XPUT 'http://testServer:9200/test/' -d '{
"settings": {
"analysis": {
"analyzer": {
"my_ngram_analyzer": {
"tokenizer": "my_ngram_tokenizer",
"filter": [
"lowercase"
],
"type" : "custom"
},
"default_search": {
"tokenizer" : "keyword",
"filter" : [
"lowercase"
]
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": "3",
"max_gram": "100",
"token_chars": []
}
}
}
},
"mappings": {
"TestObject": {
"dynamic_templates": [
{
"metadata_template": {
"match_mapping_type": "string",
"path_match": "*",
"mapping": {
"type": "multi_field",
"fields": {
"ngram": {
"type": "{dynamic_type}",
"index": "analyzed",
"index_analyzer": "my_ngram_analyzer",
"search_analyzer" : "default_search"
},
"{name}": {
"type": "{dynamic_type}",
"index": "analyzed",
"index_analyzer" : "standard",
"search_analyzer" : "default_search"
},
"sortable": {
"type": "{dynamic_type}",
"index": "analyzed",
"analyzer" : "default_search"
}
}
}
}
}
]
}
}
}'
実際には、ソートと完全一致のために未分析のフィールドのみを保持しています (「ソート可能」とも呼びます)。この構成により、クエリが「含む」クエリの場合、部分的な単語検索を簡単に取得できます。クエリターゲットに「.ngram」を追加します。私たちが抱えている問題は、「.sortable」サフィックスをいつ使用するかを決定することです。たとえば、dateUpdated でソートするリクエストを受け取った場合、そのフィールドは日付であるため、.sortable を使用したくありません。リクエストが「名前」でソートする場合、そのフィールドは文字列であるため、それを使用したいのですが、「価格」でソートしようとしている場合は使用しません。
並べ替えの前にフィールドの型をチェックするロジックは少しぎこちないようです (elasticsearch で型をチェックするのではなく、モデルをチェックインします)。以下の動的テンプレートを介して文字列以外の型を実行しないでください。ブール値と数値は、ngram フィルターを介して実行できません。
タイプに関係なく決してトークン化されないソート用の「.sortable」フィールドを常に持つ方法について、誰か提案がありますか? それとも、私たちが見ていないこの種の問題に対するより良い解決策があるでしょうか? 前もって感謝します!