web-dev-qa-db-ja.com

Elasticsearchで部分一致を行うにはどうすればよいですか?

http://drive.google.com のようなリンクがあり、リンクから「google」と一致させたい。

私が持っています:

query: {
    bool : {
        must: {
            match: { text: 'google'} 
        }
    }
}

ただし、これはテキスト全体が「google」の場合にのみ一致します(大文字と小文字は区別されないため、GoogleやGooGlEなどにも一致します)。別の文字列内の「google」と一致させるにはどうすればよいですか?

20
PraneethVT

ポイントは、使用しているElasticSearch正規表現 完全な文字列の一致 が必要です:

Luceneのパターンは常に固定されています。指定されたパターンは文字列全体に一致する必要があります

したがって、任意の文字(ただし改行)に一致させるには、_.*_パターンを使用できます。

_match: { text: '.*google.*'}
                ^^      ^^
_

もう1つのバリエーションは、文字列に改行を含めることができる場合です:match: { text: '(.|\n)*google(.|\n)*'}。このひどい_(.|\n)*_はElasticSearchの必須アイテムです。この正規表現フレーバーでは_[\s\S]_の回避策もDOTALL/Singlelineフラグも許可されていないためです。 "Lucene正規表現エンジンはPerl互換ではありませんが、より小さい範囲の演算子をサポートしています。"

9

ワイルドカードクエリを使用します。

'{"query":{ "wildcard": { "text.keyword" : "*google*" }}}'
11
weijh

部分的および全文一致の両方について、以下が機能しました

"query" : {
    "query_string" : {
      "query" : "*searchText*",
      "fields" : [
        "fieldName"
      ]
    }
5

breaking change を見つけられませんmatchの正規表現を無効にしますが、match: { text: '.*google.*'}は私のElasticsearch 6.2クラスターのいずれでも動作しません。おそらく構成可能ですか?

正規表現 動作:

"query": {
   "regexp": { "text": ".*google.*"} 
}
4
Steven Ensslen

より一般的なソリューションについては、別のアナライザーの使用または独自のアナライザーの定義を検討できます。 http://drive.google.com をトークン「http」と「drive.google.com」に分割する標準アナライザーを使用していると仮定しています。これが、完全な「drive.google.com」と比較しようとしているため、googleのみの検索が機能しない理由です。

代わりに単純なアナライザーを使用してドキュメントのインデックスを作成した場合、「http」、「drive」、「google」、および「com」に分割されます。これにより、これらの用語のいずれかを独自に一致させることができます。

1

部分一致には、 prefix または match_phrase_prefix を使用できます。