web-dev-qa-db-ja.com

Elasticsearch:部分文字列の一致を見つける

Wordの完全一致とWord /部分文字列の部分一致の両方を実行したい。たとえば、「男性用シェーバー」を検索すると、結果に「男性用シェーバー」が見つかるはずです。しかし、「en's shaver」を検索した場合は、結果に「men's shaver」も見つかるはずです。次の設定とマッピングを使用します。

インデックス設定:

PUT /my_index
{
    "settings": {
        "number_of_shards": 1, 
        "analysis": {
            "filter": {
                "autocomplete_filter": { 
                    "type":     "Edge_ngram",
                    "min_gram": 1,
                    "max_gram": 20
                }
            },
            "analyzer": {
                "autocomplete": {
                    "type":      "custom",
                    "tokenizer": "standard",
                    "filter": [
                        "lowercase",
                        "autocomplete_filter" 
                    ]
                }
            }
        }
    }
}

マッピング:

PUT /my_index/my_type/_mapping
{
    "my_type": {
        "properties": {
            "name": {
                "type":            "string",
                "index_analyzer":  "autocomplete", 
                "search_analyzer": "standard" 
            }
        }
    }
}

レコードを挿入:

POST /my_index/my_type/_bulk
{ "index": { "_id": 1            }}
{ "name": "men's shaver" }
{ "index": { "_id": 2            }}
{ "name": "women's shaver" }

クエリ:

1。完全に一致するフレーズで検索するには-> "men's"

POST /my_index/my_type/_search
{
    "query": {
        "match": {
            "name": "men's"
        }
    }
}

上記のクエリは、返される結果に「男性用シェーバー」を返します。

2。単語の部分一致で検索するには-> "en's"

POST /my_index/my_type/_search
{
    "query": {
        "match": {
            "name": "en's"
        }
    }
}

上記のクエリは何も返しません。

私もクエリを試してみました

POST /my_index/my_type/_search
{
    "query": {
        "wildcard": {
           "name": {
              "value": "%en's%"
           }
        }
    }
}

まだ何も得られません。 「部分的な単語/文字列の一致」を見つけることができないインデックスの「Edge_ngram」タイプのフィルターが原因だと考えました。 「n-gram」タイプのフィルターも試してみましたが、検索速度が遅くなります。

同じインデックス設定を使用して、正確なフレーズ一致と部分フレーズ一致の両方を実現する方法を教えてください。

45
Kruti Shukla

部分的なフィールド一致と完全一致を検索するには、フィールドを「分析しない」またはキーワードとして(テキストではなく)定義してから、ワイルドカードクエリを使用すると効果的です

これも参照

ワイルドカードクエリを使用するには、検索する文字列の両端に*を追加します。

POST /my_index/my_type/_search
{
"query": {
    "wildcard": {
       "name": {
          "value": "*en's*"
       }
    }
}
}

case insensitivityで使用するには、lowercaseフィルターとキーワードtokenizerでカスタムアナライザーを使用します。

カスタムアナライザー:

"custom_analyzer": {
            "tokenizer": "keyword",
            "filter": ["lowercase"]
        }

検索文字列を小文字にする

検索文字列をAsDとして取得する場合:* asd *に変更します

61
BlackPOP