Запрос Percolate
Запрос percolate может использоваться для сопоставления запросов, хранящихся в индексе. Сам запрос percolate содержит документ, который будет использоваться в качестве запроса для сопоставления с сохранёнными запросами.
Пример использования
Для простоты примера, в этом руководстве используется один индекс, my-index-000001, как для запросов Percolate, так и для документов. Такая настройка может хорошо работать, когда зарегистрировано небольшое количество запросов Percolate. Для более интенсивного использования рекомендуется хранить запросы и документы в отдельных индексах. Подробнее см. Как это работает под капотом.
Создайте индекс с двумя полями:
PUT /my-index-00001
{
"mappings": {
"properties": {
"message": {
"type": "text"
},
"query": {
"type": "percolator"
}
}
}
} Поле message является полем, используемым для предварительной обработки документа, определённого в запросе percolator, перед его индексированием во временный индекс.
Поле query используется для индексирования документов запроса. Оно будет содержать json-объект, представляющий фактический запрос Elasticsearch. Поле query настроено на использование типа поля percolator. Этот тип поля понимает DSL запросов и хранит запрос таким образом, чтобы его можно было использовать позднее для сопоставления документов, определённых в запросе percolate.
Зарегистрируйте запрос в percolator:
PUT /my-index-00001/_doc/1?refresh
{
"query": {
"match": {
"message": "bonsai tree"
}
}
} Сопоставьте документ с зарегистрированными запросами percolator:
GET /my-index-00001/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"message": "A new bonsai tree in the office"
}
}
}
} Вышеуказанный запрос вернёт следующий ответ:
{
"took": 13,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.26152915,
"hits": [
{
"_index": "my-index-00001",
"_type": "_doc",
"_id": "1",
"_score": 0.26152915,
"_source": {
"query": {
"match": {
"message": "bonsai tree"
}
}
},
"fields" : {
"_percolator_document_slot" : [0]
}
}
]
}
} | Запрос с идентификатором | |
| Поле |
Параметры
При выполнении percolating документа необходимы следующие параметры:
| | Поле типа |
| | Суффикс, используемый для поля |
| | Источник документа, который подлежит percolating. |
| | Аналогично параметру |
| | Тип/сопоставление документа, который подлежит percolating. Этот параметр устарел и будет удалён в Elasticsearch 8.0. |
Вместо указания источника документа для percolating, источник также может быть извлечён из уже хранящегося документа. Запрос percolate затем выполнит внутренний запрос GET для извлечения этого документа.
В этом случае параметр document можно заменить следующими параметрами:
| | Индекс, в котором находится документ. Требуемый параметр. |
| | Тип документа для извлечения. Этот параметр устарел и будет удалён в Elasticsearch 8.0. |
| | Идентификатор документа для извлечения. Требуемый параметр. |
| | Необязательно, маршрутизация для извлечения документа для percolating. |
| | Необязательно, предпочтение для извлечения документа для percolating. |
| | Необязательно, ожидаемая версия документа для извлечения. |
Percolating в контексте фильтра
В случае, если вас не интересует оценка, можно ожидать лучшей производительности, обернув запрос percolator в условие фильтра запроса bool или в запрос constant_score:
GET /my-index-00001/_search
{
"query": {
"constant_score": {
"filter": {
"percolate": {
"field": "query",
"document": {
"message": "A new bonsai tree in the office"
}
}
}
}
}
} При индексировании извлекаются термины из запроса percolator, и percolator часто может определить, соответствует ли запрос, просто посмотрев на эти извлечённые термины. Однако, вычисление оценок требует десериализации каждого соответствующего запроса и его выполнения по отношению к percolated документу, что является гораздо более дорогостоящей операцией. Поэтому, если вычисление оценок не требуется, запрос percolate должен быть обернут в запрос constant_score или в условие фильтра запроса bool.
Обратите внимание, что запрос percolate никогда не кэшируется кэш запросов.
Percolating нескольких документов
Запрос percolate может одновременно сопоставлять несколько документов с индексированными запросами percolator. Percolating нескольких документов в одном запросе может улучшить производительность, так как запросы нужно анализировать и сопоставлять только один раз вместо нескольких.
Поле _percolator_document_slot, возвращаемое с каждым сопоставленным запросом percolator, важно при одновременном percolating нескольких документов. Оно указывает, какие документы сопоставились с конкретным запросом percolator. Номера соответствуют позиции в массиве documents, указанном в запросе percolate.
GET /my-index-00001/_search
{
"query": {
"percolate": {
"field": "query",
"documents": [
{
"message": "bonsai tree"
},
{
"message": "new tree"
},
{
"message": "the office"
},
{
"message": "office tree"
}
]
}
}
} | Массив документов содержит 4 документа, которые будут percolated одновременно. |
{
"took": 13,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.7093853,
"hits": [
{
"_index": "my-index-00001",
"_type": "_doc",
"_id": "1",
"_score": 0.7093853,
"_source": {
"query": {
"match": {
"message": "bonsai tree"
}
}
},
"fields" : {
"_percolator_document_slot" : [0, 1, 3]
}
}
]
}
} |
|
Percolating Существующего Документа
Для percolating недавно индексированного документа можно использовать запрос percolate. Основываясь на ответе от запроса индекса, можно использовать _id и другую метаинформацию, чтобы немедленно percolate недавно добавленный документ.
Пример
Основываясь на предыдущем примере.
Индексируем документ, который мы хотим percolate:
PUT /my-index-00001/_doc/2
{
"message" : "A new bonsai tree in the office"
} Ответ индекса:
{
"_index": "my-index-00001",
"_type": "_doc",
"_id": "2",
"_version": 1,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"result": "created",
"_seq_no" : 1,
"_primary_term" : 1
} Percolating существующего документа, используя ответ индекса как основу для создания нового запроса поиска:
GET /my-index-00001/_search
{
"query": {
"percolate": {
"field": "query",
"index": "my-index-00001",
"id": "2",
"version": 1
}
}
} | Версия является необязательной, но полезной в определённых случаях. Она позволяет убедиться, что мы пытаемся percolate документ, который мы только что индексировали. Изменения могут быть внесены после индексирования, и в таком случае запрос поиска завершится с ошибкой конфликта версий. |
Возвращаемый ответ поиска идентичен ответу в предыдущем примере.
Запрос перколятора и выделение ключевых слов
Запрос перколятора обрабатывается особым образом при выделении ключевых слов. Для выделения используются результаты совпадений с запросом, предоставленным в запросе перколятора. В то время как при обычном выделении ключевых слов для выделения используются термины запроса в самом запросе.
Пример
Этот пример основан на отображении первого примера.
Сохраните запрос:
PUT /my-index-00001/_doc/3?refresh
{
"query": {
"match": {
"message": "brown fox"
}
}
} Сохраните другой запрос:
PUT /my-index-00001/_doc/4?refresh
{
"query": {
"match": {
"message": "lazy dog"
}
}
} Выполните запрос поиска с запросом перколятора и включенным выделением ключевых слов:
GET /my-index-00001/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"message": "The quick brown fox jumps over the lazy dog"
}
}
},
"highlight": {
"fields": {
"message": {}
}
}
} Это приведет к следующему ответу.
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 2,
"relation": "eq"
},
"max_score": 0.26152915,
"hits": [
{
"_index": "my-index-00001",
"_type": "_doc",
"_id": "3",
"_score": 0.26152915,
"_source": {
"query": {
"match": {
"message": "brown fox"
}
}
},
"highlight": {
"message": [
"The quick <em>brown</em> <em>fox</em> jumps over the lazy dog"
]
},
"fields" : {
"_percolator_document_slot" : [0]
}
},
{
"_index": "my-index-00001",
"_type": "_doc",
"_id": "4",
"_score": 0.26152915,
"_source": {
"query": {
"match": {
"message": "lazy dog"
}
}
},
"highlight": {
"message": [
"The quick brown fox jumps over the <em>lazy</em> <em>dog</em>"
]
},
"fields" : {
"_percolator_document_slot" : [0]
}
}
]
}
} | Термины из каждого запроса были выделены в документе. |
Вместо того, чтобы запрос в запросе поиска выделял результаты перколятора, запросы перколятора выделяют документ, определенный в запросе перколятора.
При перколяцией нескольких документов одновременно, как в запросе ниже, ответ выделения отличается:
GET /my-index-00001/_search
{
"query": {
"percolate": {
"field": "query",
"documents": [
{
"message": "bonsai tree"
},
{
"message": "new tree"
},
{
"message": "the office"
},
{
"message": "office tree"
}
]
}
},
"highlight": {
"fields": {
"message": {}
}
}
} Несколько измененный ответ:
{
"took": 13,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.7093853,
"hits": [
{
"_index": "my-index-00001",
"_type": "_doc",
"_id": "1",
"_score": 0.7093853,
"_source": {
"query": {
"match": {
"message": "bonsai tree"
}
}
},
"fields" : {
"_percolator_document_slot" : [0, 1, 3]
},
"highlight" : {
"0_message" : [
"<em>bonsai</em> <em>tree</em>"
],
"3_message" : [
"office <em>tree</em>"
],
"1_message" : [
"new <em>tree</em>"
]
}
}
]
}
} | Поля выделения снабжены префиксом, указывающим слот документа, к которому они относятся, чтобы было понятно, к какому документу относится какое поле выделения. |
Указание нескольких запросов перколятора
Возможна установка нескольких запросов перколятора в одном запросе поиска:
GET /my-index-00001/_search
{
"query": {
"bool": {
"should": [
{
"percolate": {
"field": "query",
"document": {
"message": "bonsai tree"
},
"name": "query1"
}
},
{
"percolate": {
"field": "query",
"document": {
"message": "tulip flower"
},
"name": "query2"
}
}
]
}
}
} | Параметр |
Имя поля _percolator_document_slot будет дополнено значением, указанным в параметре _name. Если этот параметр не указан, используется параметр field, что в этом случае может привести к неоднозначности.
Вышеуказанный запрос поиска возвращает ответ, похожий на этот:
{
"took": 13,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.26152915,
"hits": [
{
"_index": "my-index-00001",
"_type": "_doc",
"_id": "1",
"_score": 0.26152915,
"_source": {
"query": {
"match": {
"message": "bonsai tree"
}
}
},
"fields" : {
"_percolator_document_slot_query1" : [0]
}
}
]
}
} | Поле слота перколятора |
Как это работает
При индексировании документа в индекс, для которого настроено отображение типа поля перколятора, часть запроса документа парсится в запрос Lucene и сохраняется в индексе Lucene. Бинарное представление запроса сохраняется, а также термины запроса анализируются и сохраняются в индексированном поле.
При поиске документ, указанный в запросе, парсится в документ Lucene и сохраняется в временном индексе Lucene в оперативной памяти. Этот индекс в оперативной памяти может содержать только этот один документ и оптимизирован для этого. После этого строится специальный запрос, основанный на терминах в индексе оперативной памяти, который выбирает потенциальные запросы перколятора на основе их индексированных терминов запроса. Затем эти запросы оцениваются индексом оперативной памяти на предмет фактического совпадения.
Выбор потенциальных запросов перколятора является важной оптимизацией производительности при выполнении запроса percolate, так как это может существенно уменьшить количество потенциальных совпадений, которые должен оценивать индекс оперативной памяти. Причина, по которой запрос percolate может это сделать, заключается в том, что при индексировании запросов перколятора термины запроса извлекаются и индексируются вместе с запросом перколятора. К сожалению, перколятор не может извлечь термины из всех запросов (например, из запроса wildcard или geo_shape) и в результате этого в некоторых случаях перколятор не может выполнить оптимизацию выбора (например, если неподдерживаемый запрос определен в обязательной части булевой запроса или если неподдерживаемый запрос является единственным запросом в документе перколятора). Эти запросы помечаются перколятором и могут быть найдены с помощью следующего запроса:
GET /_search
{
"query": {
"term" : {
"query.extraction_result" : "failed"
}
}
} В приведенном выше примере предполагается, что существует поле query типа percolator в отображениях.
Учитывая дизайн перколяций, часто имеет смысл использовать отдельные индексы для запросов перколятора и документов, которые перколируются, а не один индекс, как в примерах. Этот подход имеет несколько преимуществ:
- Поскольку запросы перколятора содержат другой набор полей, чем перколируемые документы, использование двух отдельных индексов позволяет хранить поля более плотно и эффективно.
- Производительность перколяций не масштабируется так же, как и других запросов, поэтому производительность перколяций может улучшиться при использовании другой конфигурации индекса, например, количества основных фрагментов.
Примечания
Разрешить дорогостоящие запросы
Запросы перколятора не будут выполняться, если search.allow_expensive_queries установлено в значение false.
Использование пользовательских сходств
Запросы перколятора не будут учитывать какие-либо настроенные пользовательские сходства. Они всегда используют стандартное сходство Lucene.
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-percolate-query.html