В OpenSearch есть функция, которая, возможно, не очень известна, но очень полезна для различных целей. Как следует из названия, именованные запросы - это функция, которая позволяет обозначать запросы именем. В большинстве поисковых приложений у вас есть более одного запроса в шаблоне запроса. Это могут быть разные шаблоны или шаблон запроса с несколькими подзапросами, каждый из которых соответствует определенному требованию поиска.
Если вы добавите имя к каждому из этих низкоуровневых запросов, OpenSearch вернет список всех совпадающих запросов в ответ на каждое попадание.
Это может быть использовано в различных случаях:
Пример 1 - отладка запросов
Отладка запросов может быть значительно упрощена при использовании именованных запросов. Приходилось ли вам когда-нибудь использовать функцию _explain? Функция explain рассказывает, как именно вычислялась оценка. Это может быть полезно, но часто это слишком подробно и очень трудно для чтения.
Вас часто будут спрашивать, почему тот или иной хит был оценен выше, чем другой. Очень часто это связано с тем, что фраза запроса вообще не соответствует документу. Чтобы получить дополнительную информацию об этом и со временем уточнить и улучшить свои запросы, вы можете использовать именованные запросы.
Вариант использования 2 - специфическая логика запросов
Именованные запросы могут быть полезны, если вам нужна очень специфическая логика запроса, реализованная в бэкенде.
В электронной коммерции часто требуется вывести только один результат и перенаправить на страницу с подробной информацией, например, если запрос соответствует ID продукта.
С помощью именованных запросов очень легко реализовать эту функцию элегантным способом. Вам не нужно запускать 2 параллельных запроса, не нужно разбирать результаты запроса и применять логику, которую OpenSearch уже сделал за вас. Вы просто проверяете, не было ли среди ваших хитов точного совпадения в ID товара по названию, и затем выводите его.
Пример
Query - укажите имя для каждого пункта запроса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | GET _search { "query":{ "bool":{ "should":[ { "multi_match":{ "query":"123", "fields":[ "title", "description" ], "_name":"match content" } }, { "match":{ "product_id":{ "query":"123", "_name":"match product id" } } } ] } } } |
Response - просто используйте содержимое "matched_queries" для дальнейшей обработки в вашем бэкенд-приложении:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | { "hits":{ "total":1, "max_score":0.2876821, "hits":[ { "_index":"test", "_type":"doc", "_id":"1", "_score":0.2876821, "_source":{ "product_id":"123" }, "matched_queries":[ "match product id" ] } ] } } |
Вариант использования 3 - диверсификация результатов поиска
Еще один типичный случай использования - диверсификация результатов поиска. Вы можете захотеть сгруппировать результаты по категориям и показывать только лучшие результаты в каждой категории. Это можно легко сделать, сгруппировав результаты по определенному имени запроса в бэкенде и отобразив только лучшие хиты в каждой категории.
Вариант использования 4 - ведение журнала
Еще один важный вариант использования именованных запросов - протоколирование. Если вы ведете логгирование всех запросов, то чтение всего JSON может быть слишком большим и нечитабельным.
Если же вы будете записывать в журнал только условия запроса и совпавшие с ними запросы, а также некоторые показатели производительности, то читать и понимать их будет гораздо проще.
Пример именованного запроса
Давайте рассмотрим пример:
Сначала проиндексируем 2 документа выборки. Затем выполним bool-запрос по этому индексу. Запрос bool содержит 2 условия "should", каждое из которых помечено именем. В результате мы сможем увидеть, какие из пунктов запроса совпали.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | PUT named_queries/_doc/1 { "title" : "Cats", "content" : "Cats are cute" } PUT named_queries/_doc/2 { "title" : "Dogs", "content" : "Dogs are cute" } GET named_queries/_search { "query":{ "bool":{ "should":[ { "match":{ "title":{ "query":"cats", "_name":"title match" } } }, { "match":{ "content":{ "query":"cats", "_name":"content match" } } } ] } } } |
В результате запроса мы видим каждое совпадение с дополнительным параметром под названием "matched_queries". В нем содержатся все запросы, которые были найдены для этого документа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "hits":{ "total":{ "value":1, "relation":"eq" }, "max_score":0.5753642, "hits":[ { "_index":"named_queries", "_type":"_doc", "_id":"1", "_score":0.5753642, "_source":{ "title":"Cats", "content":"Cats are cute" }, "matched_queries":[ "title match", "content match" ] } ] } } |