Как выполнить частичное совпадение в 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"
]
}