Эластичный поиск: как завершить мульти-поиск, как только мы получим желаемый результат

У нас есть эластичный поисковый документ со строковым полем с именем "Тип". Это поле может иметь различные значения от "A" до "Z". Несколько документов могут иметь один и тот же тип, т.е. несколько документов могут иметь тип "А"

Мы хотим написать эластичный поисковый запрос, который возвращает нам максимум 30 из этих документов. Мы хотим, чтобы вывод находился в другой группе в зависимости от типа. Например:

  1. Если у нас есть 10 документов типа A, 15 типов B, 20 типов C, я должен получить все 10 с типом A, все 15 с типом B и 5 типа C.
  2. Если у нас есть 0 документов типа A, 10 типа B, 15 типа C, 20 типа D, я должен получить все 10 с типом B, 15 типа C и 5 типа D.
  3. В худшем случае: если у нас нет документов типа 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 или более результатов.

Пожалуйста, обратите внимание:

  1. Я дал очень простое условие, то есть условие различного мульти-поиска является более сложным, чем просто по типу.
  2. Мы хотим, чтобы на выходе было несколько коллекций, т.е. типа 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"
    }
  }
}

Надеюсь, это поможет!

Другие вопросы по тегам