Чтобы понять, почему запрос term
не работает так, как вы ожидаете, нам нужно проверить, как ElasticSearch
обрабатывает и сохраняет данные и чем отличаются запросы match
и term
.
Обычно, когдаВы сохраняете некоторый текст в ElasticSearch
, сначала он анализируется, а затем сохраняется.Анализ выполняется анализатором .Существует много анализаторов, но если вы не укажете их, будет использоваться стандартный.Анализатор обрабатывает текст, преобразует его в массив токенов и сохраняет список токенов.Правила разделения текста на токены различны для каждого конкретного анализатора.
Когда текст обработан и сохранен, вы можете запросить его.Существует много способов запроса чего-либо, но в вашем случае основное различие между match
и term
заключается в том, что match
- это полнотекстовый запрос , а term
- это запрос уровня термина .Дело в том, что в случае полнотекстового поиска ваша строка запроса анализируется так же, как и поле, которое вы запрашиваете.В запросах уровня термина строка запроса не анализируется.Важно отметить.
Теперь давайте посмотрим, как "OBJ_DELETED"
анализируется с помощью ElasticSearch
.Для этого мы можем добавить простой документ, подобный этому:
curl -X PUT 'localhost:9200/testdata/object/1' -H 'Content-Type: application/json' -d '{ "object_status": "OBJ_DELETED" }'
Затем убедитесь, что все есть:
curl -X POST 'localhost:9200/testdata/_search?pretty'
должно выдать что-то вроде этого:
...
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "testdata",
"_type" : "object",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"object_status" : "OBJ_DELETED"
}
}
]
}
Теперь мы можем проверить, как анализируется "OBJ_DELETED"
:
curl -X POST 'localhost:9200/testdata/_analyze?pretty' -H 'Content-Type: application/json' -d '{ "text": "OBJ_DELETED" }'
и он выводит:
{
"tokens" : [
{
"token" : "obj_deleted",
"start_offset" : 0,
"end_offset" : 11,
"type" : "<ALPHANUM>",
"position" : 0
}
]
}
Как вы можете видеть, он конвертирует только текст в нижний регистри сохранил его как один токен.Вот как это делает анализатор по умолчанию.Теперь вернемся к вашим запросам.match
запрос работает, потому что значение запроса "OBJ_DELETED"
также преобразуется в нижний регистр под капотом и, таким образом, ElasticSearch
может его найти.И для term
запроса строка запроса не обрабатывается, так что на самом деле вы сравниваете OBJ_DELETED
с obj_deleted
и, очевидно, вы не получаете результатов.
И последний вопрос: почему object_status.keyword
работает для term
query?
По умолчанию ElasticSearch
создать дополнительное отображение для каждого текстового поля.Это своего рода метаданные, которые вы можете использовать.Также это позволяет обрабатывать одно и то же значение по-разному.Таким образом, по умолчанию каждое поле text имеет дополнительное сопоставление с именем keyword
, которое имеет тип ключевое слово .keyword
поля не анализируются (их можно нормализовать только при необходимости).Это означает, что для отображения по умолчанию сохраняется точное значение, которое вы передаете ElasticSearch
(OBJ_DELETED
в вашем случае).