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

У меня есть ссылка типа http://drive.google.com и я хочу, чтобы матч "Гугл" из ссылки.

Я:

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

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

5 ответов


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

узоры Люсена всегда закреплены. Шаблон при условии должен соответствовать всей строке.

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

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

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


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

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

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

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


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

Regexp работает:

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

для частичного сопоставления вы можете использовать префикс или match_phrase_prefix.