Эластичный поисковый запрос для различных вложенных значений

Я использую REST-клиент высокого уровня для эластичного поиска 6.2.2. Предположим, что у меня есть два документа в индексе "ДОКУМЕНТЫ" с типом "ДОКУМЕНТЫ", которые

{
   "_id": 1,
   "Name": "John",
   "FunFacts": {
       "FavColor": "Green",
       "Age": 32
   }
},
{
   "_id": 2,
   "Name": "Amy",
   "FunFacts": {
       "FavFood": "Pizza",
       "Age": 33
   }
}

Я хочу выяснить все интересные факты и их ценности, в конечном итоге возвращая конечный результат

{
    "FavColor": ["Green"],
    "Age": [32, 33],
    "FavFood": ["Pizza"]
}

Это нормально, если для этого требуется более одного запроса в Elastic Search, но я предпочитаю иметь только один запрос. Кроме того, индекс Elastic Search может вырасти до довольно большого, поэтому я должен заставить как можно больше выполнения на экземпляре ES.

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

SearchRequest searchRequest = new SearchRequest("DOCUMENTS");
searchRequest.types("DOCUMENTS");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
String [] includes = new String[1];
includes[0] = "FunFacts";
String [] excludes = new String[1];
excludes[0] = "Name";
searchSourceBuilder.fetchSource(includes, excludes);
searchRequest.source(searchSourceBuilder);

SearchResponse searchResponse =
    restHighLevelClient.search(searchRequest);

Может кто-то указать мне верное направление? Я заметил, что почти вся документация Elastic Search поставляется в форме curl команды, что мне не полезно, так как я недостаточно разбираюсь в том, чтобы переводить такие команды в JAVA.

Вот ваш поворот сюжета. Поскольку пользователям разрешается решать, что будет их забавным фактом, мы не можем заранее знать, какие будут ключи внутри FunFacts Карта.:/

Спасибо Мэтт

1 ответ

Решение

Вы можете сделать все это в одном запросе с помощью агрегатов. Предполагая, что у вас есть следующие документы в вашем индексе

{
   "Name": "Jake",
   "FunFacts": {
       "FavFood": "Burgers",
       "Age": 32
   }
}

{
   "Name": "Amy",
   "FunFacts": {
       "FavFood": "Pizza",
       "Age": 33
   }
}

{
   "Name": "Alex",
   "FunFacts": {
       "FavFood": "Burgers",
       "Age": 28
   }
}

и вы хотите получить различные варианты "FavFood", вы можете сделать это, используя следующие агрегации терминов ( документы по этой теме)

{
  "aggs": {
    "disticnt_fun_facts": {
      "terms": { "field": "FunFacts.FavFood" }
    }
  }
}

что приведет к чему-то в этом направлении

{
  ...
  "hits": { ... },
  "aggregations": {
    "disticnt_fun_facts": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "burgers",
          "doc_count": 2
        },
        {
          "key": "pizza",
          "doc_count": 1
        }
      ]
    }
  }
}

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

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

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