Поиск общих значений поля массива двух документов в ElasticSearch

У меня есть два документа в эластичном поиске со следующими значениями

uid  preferences
1    [10,20,30,40,50,60,70,80,100]
2    [20,70,30,100,1000,77,45]

Можем ли мы каким-либо образом пересечь массив настроек для этих двух записей и получить результат [20,70,30,100]? В настоящее время мы получаем эти две записи на сервер приложений и выполняем пересечение, но хотели проверить, есть ли какой-либо прямой способ получить значения пересечения напрямую из Elasticsearch. Спасибо.

Пересекаются значения для чего? На группу идентификаторов документов? Или просто пара 2, как в вашем примере?

Joe - ElasticsearchBook.com 16.12.2020 21:05

Спасибо @JoeSorocin за ваш комментарий. Пара из 2, как указано в примере, в порядке.

Bujji 17.12.2020 02:41
0
2
195
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я бы решил эту проблему, используя параметризованную агрегацию метрик по сценарию. Вот более читаемая версия:

{
  "size": 0,
  "query": {
    "terms": {
      "id": [
        1,
        2
      ]
    }
  },
  "aggs": {
    "preferences_intersection": {
      "scripted_metric": {
        "init_script": "state.shared_vals = [];",
        "map_script": "state.shared_vals.addAll(new ArrayList(doc['preferences']));",
        "combine_script": """
          return state.shared_vals.stream()
                                  .filter(i -> Collections.frequency(state.shared_vals, i) >= params.compared_docs_count)
                                  .sorted((o1, o2) -> o1.compareTo(o2))
                                  .collect(Collectors.toCollection(TreeSet::new))
        """,
        "reduce_script": "return states[0]",
        "params": {
          "compared_docs_count": 2
        }
      }
    }
  }
}

Обратите внимание, как запрос terms был применен вместе с params.compared_docs_count, чтобы мы могли проверить количество вхождений общих значений.

Вот компактная версия запроса без тройных кавычек:

{"size":0,"query":{"terms":{"id":[1,2]}},"aggs":{"preferences_intersection":{"scripted_metric":{"init_script":"state.shared_vals = [];","map_script":"state.shared_vals.addAll(new ArrayList(doc['preferences']));","combine_script":"          return state.shared_vals.stream()\n                                  .filter(i -> Collections.frequency(state.shared_vals, i) >= params.compared_docs_count)\n                                  .sorted((o1, o2) -> o1.compareTo(o2))\n                                  .collect(Collectors.toCollection(TreeSet::new))","reduce_script":"return states[0]","params":{"compared_docs_count":2}}}}}

Спасибо @JoeSorocin за ваш ответ. Поскольку это сценарий, основанный на размышлениях о проблемах с производительностью. Удачи вашему «Руководству по Elasticsearch»

Bujji 17.12.2020 21:21

Спасибо! Да, скрипты, как правило, медленные, но в этом мы просматриваем только 2 документа благодаря запросу terms, поэтому я бы не стал об этом беспокоиться.

Joe - ElasticsearchBook.com 17.12.2020 22:28

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