match против term: анализируемые и точные поля
Разбираем главную развилку поиска в Elasticsearch — когда брать match, а когда term, и почему путаница тут источник большинства ошибок.
match анализирует запрос (разбивает на термы, приводит к нижнему регистру) и ищет в анализируемом поле; term ищет точное, неизменённое значение.
Две природы полей
Вспомним маппинг: поле text при индексации проходит через анализатор и хранится как набор термов; поле keyword хранится как есть, целиком. Запросы должны соответствовать этой природе: для текста — анализируемый match, для точных значений — буквальный term.
match — для полнотекстового поиска
Запрос match прогоняет вашу строку через тот же анализатор, что и поле. Запрос «Кофемашины DeLonghi» превратится в термы кофемашин, delonghi и найдёт документы с этими словами в любом регистре и форме.
{
"query": {
"match": { "title": "Кофемашины DeLonghi" }
}
}По умолчанию слова объединяются по OR: подойдут документы хотя бы с одним термом. Их можно объединить по AND:
{
"query": {
"match": {
"title": { "query": "кофемашина delonghi", "operator": "and" }
}
}
}term — для точных значений
Запрос term берёт значение буквально, без анализа, и ищет точное совпадение терма. Идеален для keyword-полей: статус, тег, id, email.
{
"query": {
"term": { "status": "published" }
}
}Классическая ловушка
Если применить term к полю text, поиск часто ничего не находит. Почему: в индексе поле text хранится как термы после анализа (например, «Кофемашина» стала кофемашина в нижнем регистре). А term сравнивает с тем, что вы написали, буквально — «Кофемашина» с большой буквы не совпадёт с термом кофемашина. Поэтому term по text — почти всегда ошибка.
| Запрос | Анализирует ввод? | Для каких полей |
match | да | text |
term | нет | keyword, числа, даты, boolean |
Как работает под капотом
При match ES берёт строку запроса, пропускает через анализатор поля, получает список термов и для каждого делает лукап в инвертированном индексе, затем объединяет постинг-листы (по OR или AND). При term анализа нет: строка сразу используется как терм для лукапа. Вот почему регистр и форма слова критичны для term и неважны для match.
Частые ошибки
- term по text-полю. Самая частая причина «поиск ничего не находит». Лечится переходом на match или на keyword-поле.
- match по keyword с расчётом на анализ. Поле keyword не анализируется при индексации, поэтому match по нему по сути сведётся к точному сравнению — пользы от анализатора не будет.
Итоги
matchанализирует запрос и предназначен для полнотекстового поиска поtext.termищет точное значение без анализа — дляkeyword, чисел, дат, boolean.termпо полюtextпочти всегда даёт пустой результат из-за расхождения регистра и форм.