5

検索と並べ替えの両方で、トークン化されたフィールドとトークン化されていないフィールドを最適に管理する方法を見つけるのに苦労しています。私たちの目標は非常に簡単です。

  1. 部分単語検索をサポート
  2. すべてのフィールドでソートをサポート
  3. マッピングは動的でなければならず、顧客は実行時に新しいフィールドを追加します。

これは動的テンプレートを使用して実現できます。デフォルトのトークナイザー、カスタムの 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」フィールドを常に持つ方法について、誰か提案がありますか? それとも、私たちが見ていないこの種の問題に対するより良い解決策があるでしょうか? 前もって感謝します!

4

1 に答える 1

6

これが実際に突き詰めたのは、マップされたすべてのフィールドに「ソート可能な」フィールド (他の用途があるため、「unanalyzed」に名前を変更した) が常に必要だったということです。すべての型に新しい動的テンプレートを追加せずにこれを行う本当の秘訣は、文字列以外のすべての型に適用できる動的テンプレートを作成することでした。match_patternそのためには、正規表現に設定する必要があります:

           {
                "other_types": {
                    "match_mapping_type": "date|boolean|double|long|integer",
                    "match_pattern": "regex",
                    "path_match": ".*",
                    "mapping": {
                        "type": "multi_field",
                        "fields": {
                            "{name}": {
                                "type": "{dynamic_type}",
                                "index": "not_analyzed"
                            },
                            "unanalyzed": {
                                "type": "{dynamic_type}",
                                "index": "not_analyzed"
                            }
                        }
                    }
                }
            } 

「path_match」にも小さな変更を加える必要があることに注意してください-実際の正規表現を使用する必要があります(ESの「単純な」表現である「*」とは対照的に)。

これの 1 つの欠点は、インデックスのサイズを大きくしていることです。これらの型をすべて 2 回格納しています。ただし、私たちの目的のために、インデックス (多数あります) は大きくなる余地が十分にあり、並べ替えまたは完全一致クエリを実行する前に、すべてのフィールドで型検索を行う必要がないようにする価値があります (常に $ を使用します)。 {fieldName}.unanalyzed)。

于 2013-11-05T16:31:49.137 に答える