Эластичный поиск: как завершить мульти-поиск, как только мы получим желаемый результат
У нас есть эластичный поисковый документ со строковым полем с именем "Тип". Это поле может иметь различные значения от "A" до "Z". Несколько документов могут иметь один и тот же тип, т.е. несколько документов могут иметь тип "А"
Мы хотим написать эластичный поисковый запрос, который возвращает нам максимум 30 из этих документов. Мы хотим, чтобы вывод находился в другой группе в зависимости от типа. Например:
- Если у нас есть 10 документов типа A, 15 типов B, 20 типов C, я должен получить все 10 с типом A, все 15 с типом B и 5 типа C.
- Если у нас есть 0 документов типа A, 10 типа B, 15 типа C, 20 типа D, я должен получить все 10 с типом B, 15 типа C и 5 типа D.
- В худшем случае: если у нас нет документов типа A ... Y и 30 документов типа Z, я должен получить 30 документов типа Z.
Для этого я написал очень простой многоканальный запрос (всего 26 запросов), т.е.
POST _msearch/
{"index":"<index_name>","type":"<type>"}
{"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["A"]}}]}}}
{"index":"<index_name>","type":"<type>"}
{"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["B"]}}]}}}
...
{"index":"<index_name>","type":"<type>"}
{"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["Z"]}}]}}}
Я обеспокоен выполнением запросов с несколькими поисковыми запросами, то есть для случая 1 и случая 2 мы получили достаточные выходные данные, т.е. 30 документов по первым нескольким запросам, тогда зачем нам выполнять остальные запросы по нескольким поискам? Есть ли способ остановить операцию мульти-поискового запроса, как только мы получим желаемое количество результатов, т.е. прекратить мульти-поиск, как только мы получим 30 или более результатов.
Пожалуйста, обратите внимание:
- Я дал очень простое условие, то есть условие различного мульти-поиска является более сложным, чем просто по типу.
- Мы хотим, чтобы на выходе было несколько коллекций, т.е. типа A, типа B и т. Д., Все в разных коллекциях (из-за этого ограничения нам пришлось исключить безболезненный вариант скрипта)
1 ответ
Похоже, что вы можете достичь того, что вы хотите с помощью одного поиска с size
и sort
плюс опционально bool
объединить запросы в один.
Могу ли я досрочно прекратить многопользовательский запрос?
Нет. Из документации Multi Search мы можем сделать вывод. Он выполняет несколько поисковых запросов с определенным уровнем параллелизма и отправляет результат только после завершения всех запросов.
Это очень похоже на Bulk API, способ легко выполнять параллельные запросы.
Могу ли я получить соответствующие документы, но в определенном порядке?
Да это то что sort
для. Для достижения поведения, описанного в оригинальном посте, достаточно буквально использовать этот вызов:
POST /<index_name>/<index_type>/_search?sort=type:asc&size=30
Могу ли я сделать один поисковый запрос по нескольким индексам и при этом использовать sort
?
Да, вам просто нужно определить список индексов:
POST /multisearch1,mutlisearch2/<index_type>/_search?sort=type:asc&size=30
Или подстановочное выражение:
POST /multisearch*/<index_type>/_search?sort=type:asc&size=30
Могу ли я сделать сортировку в произвольном порядке?
Да, например, с использованием сортировки на основе сценариев. Если, например, вы хотите увидеть type
в ваших результатах в таком порядке: X
, C
, A
Вы могли бы написать скрипт, как это:
POST /<index_name>/<type>/_search
{
"size": 30,
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": """
int r = 1;
if(doc['type'].value == 'X') {
r = 100;
} else if(doc['type'].value == 'C') {
r = 10;
} else if(doc['type'].value == 'A') {
r = 5;
}
r;
"""
},
"order": "desc"
}
}
}
Это также будет работать с несколькими коллекциями (как запрос выше).
Могу ли я сделать это, если у меня сложный запрос, который зависит от значения type
?
Да, нет проблем, используйте bool
запрос к примеру:
POST /<index_name>/<type>/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"type": "A"
}
},
{
"match": {
"description": "Quick fox"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"type": "X"
}
},
{
"match": {
"description": "Quick bear"
}
}
]
}
}
]
}
},
"size": 30,
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": """
int r = 1;
if(doc['type'].value == 'X') {
r = 100;
} else if(doc['type'].value == 'C') {
r = 10;
} else if(doc['type'].value == 'A') {
r = 5;
}
r;
"""
},
"order": "desc"
}
}
}
Надеюсь, это поможет!