Как выполнить частичное совпадение в Elasticsearch?

У меня есть ссылка вроде http://drive.google.com, и я хочу сопоставить "google" со ссылкой.

У меня есть:

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

Но это только соответствует, если весь текст "google" (регистр нечувствителен, поэтому он также соответствует Google или GooGlE и т.д.). Как я могу сопоставить "google" внутри другой строки?

Ответ 1

Дело в том, что регулярное выражение ElasticSearch, которое вы используете требует полного соответствия строк:

Модели Lucenes всегда привязаны. Шаблон должен соответствовать всей строке.

Таким образом, чтобы соответствовать любому символу (но новой строке), вы можете использовать шаблон .*:

match: { text: '.*google.*'}
                ^^      ^^

Еще один вариант - для случаев, когда строка может иметь символы новой строки: match: { text: '(.|\n)*google(.|\n)*'}. Этот ужасный (.|\n)* является обязательным в ElasticSearch, потому что этот аромат регулярного выражения не позволяет использовать обходные пути [\s\S], а также любые флаги DOTALL/Singleline. Механизм регулярных выражений Lucene не совместим с Perl, но поддерживает меньший диапазон операторов.

Ответ 2

используйте подстановочный запрос:

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

Ответ 3

Я не могу найти нарушение изменений, отключая регулярные выражения в match, но match: { text: '.*google.*'} не работает ни на одном из моих Классы Elasticsearch 6.2. Возможно, он настраивается?

Regexp работает:

"query": {
   "regexp": { "text": ".*google.*"} 
}

Ответ 4

Для более общего решения вы можете изучить использование другого анализатора или определить свой собственный. Я предполагаю, что вы используете стандартный анализатор, который разделил бы http://drive.google.com на токены "http" и "drive.google.com". Вот почему поиск только Google не работает, потому что он пытается сравнить его с полным "drive.google.com".

Если вместо этого вы проиндексировали свои документы с помощью простого анализатора, он разделил бы его на "http", "drive", "google" и "com". Это позволит вам сопоставить любой из этих условий самостоятельно.

Ответ 5

Для частичного соответствия вы можете либо использовать prefix, либо match_phrase_prefix.

Ответ 6

Как для частичного, так и для полнотекстового соответствия, сработало следующее

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