Ненахождение ожидаемых результатов по точному запросу
Довольно часто начинающие пользователи пытаются и не могут найти точное совпадение (либо получают много неожиданных совпадений) по некоторому запросу, например, по uuid:
{
"query": {
"match": {
"request-id": "e5e7dd24-b8ae-4930-8886-9151ce9d1587"
}
}
}
результат:
[
{
"_index": "requests",
"_type": "_doc",
"_id": "VY2zdGsBBVofJXj9PWTx",
"_score": 1.4224334,
"_source": {
"request-id": "e5e7dd24-b8ae-4930-8886-9151ce9d1587"
}
},
{
"_index": "requests",
"_type": "_doc",
"_id": "WI2zdGsBBVofJXj9cGS-",
"_score": 1.1507283,
"_source": {
"request-id": "e5e7dd24-b8ae-4930-8886-9151ce9d1590"
}
},
{
"_index": "requests",
"_type": "_doc",
"_id": "V42zdGsBBVofJXj9aGR8",
"_score": 1.1507283,
"_source": {
"request-id": "e5e7dd24-b8ae-4930-8886-9151ce9d1589"
}
},
{
"_index": "requests",
"_type": "_doc",
"_id": "Vo2zdGsBBVofJXj9WmR2",
"_score": 0.72928625,
"_source": {
"request-id": "e5e7dd24-b8ae-4930-8886-9151ce9d1588"
}
}
]
Это связано с тем, что по умолчанию ElasticSearch бьет текстовые поля на
токены, и подобный текст, будучи встреченный на этапе индексирования,
превратится в пять токенов: e5e7dd24
, b8ae
, 4930
, 8886
и
9151ce9d1587
, и ищет аналогичным способом (разбивая текст на токены),
таким образом “точного совпадения” для подобной строки просто не
существует - существует только полное совпадение отдельных токенов.
Подробнее про анализ во время индексации и поиска можно прочитать на странице документации по анализу.
Как с этим бороться?
Если вам необходимо искать точное совпадение строки, как с другими типами данных, то рационально использовать тип keyword для таких данных, который подразумевает хранение и поиск по строке в исходном виде. Семантическое отличие keyword от text состоит в том, что первый предназначен для поиска точных значений, а второй - для полнотекстового поиска, который и вызывает вышеописанные аномалии.
Создание индекса:
PUT requests
{
"mappings": {
"_doc": {
"properties": {
"request-id": {
"type": "keyword"
}
}
}
}
}
Результат:
[
{
"_index": "requests",
"_type": "_doc",
"_id": "VY2zdGsBBVofJXj9PWTx",
"_score": 1.4224334,
"_source": {
"request-id": "e5e7dd24-b8ae-4930-8886-9151ce9d1587"
}
}
]
Конкретно в вышеописанном случае можно заставить match query искать совпадение всех токенов (однако вероятнее всего вам лучше использовать предыдущую рекомендацию):
{
"query": {
"match": {
"request-id": {
"query": "e5e7dd24-b8ae-4930-8886-9151ce9d1587",
"operator": "and"
}
}
}
}
Что вернет единственный и ожидаемый документ:
[
{
"_index": "requests",
"_type": "_doc",
"_id": "VY2zdGsBBVofJXj9PWTx",
"_score": 1.4224334,
"_source": {
"request-id": "e5e7dd24-b8ae-4930-8886-9151ce9d1587"
}
}
]