ElasticSearch: Каков наилучший способ найти отдельные даты в диапазоне дат, который содержит документы? - PullRequest
0 голосов
/ 19 октября 2018

Допустим, у меня есть месячные индексы, содержащие два поля, которые важны для фильтрации документа: client_id и date_time, и несколько других полей данных, которые меня не интересуют.

Если я хочу найтивсе разные date_time, которые существуют в моем индексе в течение определенного периода времени (т. е. если бы это были заказы, были бы все даты, которые были заказами, зарегистрированными в периоде, если бы это были арендованные автомобили, то были бы все дни, когда были арендованы автомобили,и т. д.)

Допустим, я хочу найти другой dateTime, существующий в ES для 2018-10-01 и 2018-10-03 (сокращенно для этого примера)

Я могу начать с добавлениязапрос bool, чтобы ограничить эти данные диапазоном дат:

{
  "size" : 0,
  "timeout" : 1500,
  "query" : {
    "bool" : {
      "must" : {
        "range" : {
          "date_time" : {
            "from" : "2018-10-01T00:00:00.000Z",
            "to" : "2018-10-03T23:59:59.999Z",
            "include_lower" : true,
            "include_upper" : true
          }
        }
      }
    }
  }
} 

Я выполняю агрегацию диапазонов дат и фильтрую по количеству документов по коду:

{
  "size" : 0,
  "timeout" : 1500,
  "query" : {
    "bool" : {
      "must" : {
        "range" : {
          "date_time" : {
            "from" : "2018-09-19T00:00:00.000Z",
            "to" : "2018-10-19T23:59:59.999Z",
            "include_lower" : true,
            "include_upper" : true
          }
        }
      }
    }
  },
  "aggregations" : {
    "date_range_agg" : {
      "date_range" : {
        "field" : "date_time",
        "ranges" : [ {
          "from" : "2018-09-30T00:00:00.000Z",
          "to" : "2018-10-01T00:00:00.000Z"
        }, {
          "from" : "2018-10-01T00:00:00.000Z",
          "to" : "2018-10-02T00:00:00.000Z"
        }, {
          "from" : "2018-10-02T00:00:00.000Z",
          "to" : "2018-10-03T00:00:00.000Z"
        }, {
          "from" : "2018-10-03T00:00:00.000Z",
          "to" : "2018-10-04T00:00:00.000Z"
        }]
      }
    }
  }
} 

Я могу просто отфильтроватьсегменты из date_range_agg в моем коде, используя doc_count> 0, но мне все еще не нравится.

Есть ли способ применить фильтр к сегменту date_range, чтобы получить только теe ведра, которые содержат более 0 документов?

Есть ли другой способ сделать "sql group by", как agg поля date_time, чтобы получить все отличные в ES для диапазона дат?

Короче говоря, мне нужно только получить все разные date_time, которые на самом деле имеют документы за определенный период времени.

Мы говорим об индексах с документами на 7 ГБ (около 1,6 миллиона документов на индекс), или индексы 3,8 ГБ и 2 миллиона документов.Поэтому я пытаюсь найти наиболее эффективный способ получить это.

ДОБАВЛЕНО - ПРИМЕЧАНИЕ: На самом деле, этот запрос используется для проверки существования данных в день во всех наших индексах,некоторые из них действительно маленькие, а некоторые такие огромные, и могут истекать время ожидания, все они имеют поле dateTime, и все они с отметкой времени, соответствующей миллису дня 0, и одинаковым часовым поясом, поэтому они выигралине изменяется в миллисекундах или в чем-либо .

Ответы [ 2 ]

0 голосов
/ 20 октября 2018

Я думаю, что ниже запрос это то, что вы ищете.Я реализовал range part из aggregation с использованием гистограммы дат и использовал агрегацию селектора сегментов , чтобы возвращались только те диапазоны, которые имеют document count>0.

{  
   "size":0,
   "timeout":"1500ms",
   "query":{  
      "bool":{  
         "must":{  
            "range":{  
               "date_time":{  
                  "from":"2018-09-19T00:00:00.000Z",
                  "to":"2018-10-19T23:59:59.999Z",
                  "include_lower":true,
                  "include_upper":true
               }
            }
         }
      }
   },
   "aggregations":{  
      "date_range_agg":{  
         "date_histogram":{  
            "field":"date_time",
            "format":"MM-dd-yyyy",
            "interval":"week"
         },
         "aggs":{  
            "count_bucket_selector":{  
               "bucket_selector":{  
                  "buckets_path":{  
                     "count":"_count"
                  },
                  "script":{  
                     "lang":"expression",
                     "inline":"count>0"
                  }
               }
            }
         }
      }
   }
}

Таким образом, приведенный выше запрос вернет вам список недель и количество документов на эту неделю.И если бы на этой неделе не было документов, она бы не отображалась на этой неделе.

Вы можете использовать month или day вместо week в вышеприведенном запросе, если вы хотите видеть детали ежемесячно или ежедневно соответственно.

Производительность

Вместо того, чтобы указывать timeout, я бы посоветовал вам поэкспериментировать с функцией profiling , чтобы дать вам представление о том, сколько времени требуется для выполнения запросов агрегации.

Ниже вы можете добавить параметр профилирования в свой запрос.

{
    "profile": true,
    "size": 0,
    "query": {}
}

Вы сможете просмотреть отдельный объект JSON с profile в своем ответе, когда добавите это.В ответ вы сможете просмотреть подробную информацию о производительности запросов для каждого сегмента.В частности, обратитесь к разделу aggregation, и вы также можете обратиться к этой ссылке , чтобы узнать больше о разбивке по времени.

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

0 голосов
/ 20 октября 2018

Запрос диапазона дат с агрегированием терминов в datetype.keyword должен возвращать уникальные даты в виде идентификаторов сегментов

...