Результаты фильтрации elasticsearch содержат только уникальные документы, основанные на одном значении поля

Все мои документы имеют поле uid с идентификатором, который связывает документ с пользователем. Существует несколько документов с тем же uid.

Я хочу выполнить поиск по всем документам, возвращающим только самый высокий скоринговый документ на уникальный uid.

Запрос, выбирающий соответствующие документы, представляет собой простой запрос multi_match.

Ответ 1

Вам нужна агрегация top_hits.

И для вашего конкретного случая:

{
  "query": {
    "multi_match": {
      ...
    }
  },
  "aggs": {
    "top-uids": {
      "terms": {
        "field": "uid"
      },
      "aggs": {
        "top_uids_hits": {
          "top_hits": {
            "sort": [
              {
                "_score": {
                  "order": "desc"
                }
              }
            ],
            "size": 1
          }
        }
      }
    }
  }
}

Приведенный выше запрос выполняет ваш запрос multi_match и объединяет результаты на основе uid. Для каждой корзины uid возвращается только один результат, но после того, как все документы в _score были отсортированы на основе _score в порядке убывания.

Ответ 2

В ElasticSearch 5.3 добавлена поддержка свертывания полей. Вы должны быть в состоянии сделать что-то вроде:

GET /_search
{
  "query": {
    "multi_match" : {
      "query":    "this is a test", 
      "fields": [ "subject", "message", "uid" ] 
    }
  },
  "collapse" : {
    "field" : "uid" 
  },
  "size": 20,
  "from": 100
}

Преимущество использования свертывания полей вместо агрегации наиболее популярных попаданий состоит в том, что вы можете использовать нумерацию страниц при свертывании полей.