Агрегирование по двум полям возвращает нули для одного из них

#elasticsearch

#elasticsearch

Вопрос:

У меня есть индекс с большим количеством записей со многими полями, включая «cacheName» и «cache_ip». Каждое уникальное значение «cacheName» содержит 1 или более записей с 1 или более значениями соответствующего «cache_ip». Каждая запись также имеет уникальное поле ‘ts’ (временная метка). Например:

 {
"cacheName": "c001.abc001.xyz",
"cache_ip": "1.1.1.0",
},
{
"cacheName": "c001.abc001.xyz",
"cache_ip": "1.1.2.0",
},
{
"cacheName": "c002.efg001.mno",
"cache_ip": "1.1.9.1",
},
{
"cacheName": "c002.efg001.mno",
"cache_ip": "1.1.9.1",
},
  

Я пытаюсь создать поиск, который вернет, самое большее, каждую уникальную запись ‘cacheName’ и ‘cache_ip’. В приведенном выше примере я бы вернул в общей сложности 3 обращения («cacheName» =»c002.efg001.mno» было бы возвращено только один раз, поскольку оно имеет только одну уникальную перестановку).

Это самое близкое, к чему я пришел, но оно всегда возвращает нулевое значение для «cache_ip» вместо фактического значения (в фактических данных нет нулевых значений):

 { 
 "size": 0, 'sort': [{'ts': {'order': 'desc'}}], 
 "query": { 
             "bool": { 
                 "must": [ 
                     {"match_all": {}}, 
                     {"range": {'ts': {'gte': '20200818T010100Z', 'format': 'basic_date_time_no_millis'}}}, 
                 ] 
             } 
         }, 
 "aggs": { 
             "cacheName": { 
                 "terms": { 
                     "field": "cacheName", 
                     "size": 10000, "order": {"_key": "desc"}, 
                     }, 
                 "aggs": { 
                     "cache_ip": {"terms": {"field": "cache_ip"}}, 
                     }, 
              }, 
       }, 
}
  

Я был бы признателен за любую информацию, поскольку я из кожи вон лезу, пытаясь заставить это работать.

Спасибо!

Комментарии:

1. Получаете ли вы какие-либо результаты при выполнении этого запроса: GET your-index/_search?q=NOT(_exists_:cache_ip)

2. Нет, нулевые записи, возвращенные из этого поиска.

3. Каков тип сопоставления cache_ip ?

4. Сопоставление является строкой для этого поля

5. Хорошо, тогда в этом проблема. Это должно быть keyword или ip

Ответ №1:

Один из способов достичь желаемого — использовать сценарии для создания всех перестановок, и вам не понадобится вторая terms подагрегация:

 {
  "size": 0,
  "sort": [
    {
      "ts": {
        "order": "desc"
      }
    }
  ],
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "ts": {
              "gte": "20200818T010100Z",
              "format": "basic_date_time_no_millis"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "cacheName": {
      "terms": {
        "script": {
          "source": "[doc.cache_name.value ?: 'no.name', doc.cache_ip.value ?: 'no.ip'].join('-')"
        },
        "size": 10000,
        "order": {
          "_key": "desc"
        }
      }
    }
  }
}
  

Комментарии:

1. К сожалению, на моем сервере отключены сценарии, поэтому это будет невозможно. Существуют ли какие-либо другие решения?

2. Да, вам нужно переиндексировать ваши данные, добавив новое поле, которое содержит объединение двух полей, в основном то, что скрипт выполняет динамически

3. Хорошо, это будет непросто осуществить, поскольку я работаю в рамках очень строгих ограничений на поля и индексы. Хотя спасибо.

4. Нет, для внесения этих изменений потребуется много времени. Вероятно, месяцы.