Как создать запрос, который может рассчитать разницу во времени?

У меня есть и индекс со следующими документами:

{name: 'Device1', type: 'start', 'eventTime': '2013-02-19 12:00:00'}
{name: 'Device2', type: 'start', 'eventTime': '2013-02-19 12:02:00'}
{name: 'Device1', type: 'stop', 'eventTime': '2013-02-19 12:45:00'}
{name: 'Device2', type: 'stop', 'eventTime': '2013-02-19 12:50:00'}

Я хотел бы создать запрос, который вернет мне новое поле с разницами во времени между eventTime, ограненными именем устройства и отношениями с типом поля. Для примера это должно быть:

{name: 'Device1', 'type': 'it really doesnt matter', eventTime: 'also doesnt matter', duration: '00:45:00'}
{name 'Device2', 'type': 'it really doesnt matter', eventTime: 'also doesnt matter', duration: '00:48:00'}

Возможно ли это с помощью языка поиска с эластичным поиском?

Ответы

Ответ 1

Я не считаю, что это возможно с тем, как у вас есть каждый документ в настоящее время. Если вы храните документы как:

{name: 'Device1', startTime: '2013-02-19 12:00:00', endTime: '2013-02-19 12:45:00'}
{name: 'Device2', startTime: '2013-02-19 12:02:00', endTime: '2013-02-19 12:50:00'}

Затем вы можете вернуть поле script, которое представляет собой разницу во времени.

{    
  "query" : {
    ...
  },
  "script_fields" : {
    "timedifference" : {
      "script" : "doc['endTime'].value - doc['startTime'].value"
    }
  }
}

Ответ 2

Вы можете посмотреть elapsed фильтр статистов.

В вашем случае использования вам нужно пометить начальный документ с помощью start_tag и остановить документ с помощью end_tag. Вы можете использовать "имя" как уникальное поле id.

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

Ответ 3

Ищет то же самое, здесь Я нашел хороший пример, чтобы ответить на этот вопрос, используя прошедшие фильтры, как сказал Ана, и объединив его с агрегатным фильтром.

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

Итак, следуя примеру, указанному в ссылке, если у вас есть эти журналы:

2016-05-19T02:55:29.003 00e02f2f-32d5-9509-870a-f80e54dc8775 system1Enter
2016-05-19T02:55:29.200 00e02f2f-32d5-9509-870a-f80e54dc8775 system1Exit
2016-05-19T02:55:29.205 00e02f2f-32d5-9509-870a-f80e54dc8775 system2Enter
2016-05-19T02:55:29.453 00e02f2f-32d5-9509-870a-f80e54dc8775 system2Exit

Мы определяем три прошедших фильтра (по одному для каждого этапа в 1, 1- > 2 и в 2), а затем три совокупных фильтра, чтобы суммировать всю информацию о времени.

filter {
  grok {
    match => ["message", "%{TIMESTAMP_ISO8601:timestamp} %{UUID:messageId} %{WORD:event}"]
    add_tag => [ "%{event}" ]
  }
  date {
    match => [ "timestamp", "ISO8601"]
  }
  # Measures the execution time of system1
  elapsed {
    unique_id_field => "messageId"
    start_tag => "system1Enter"
    end_tag => "system1Exit"
    new_event_on_match => true
    add_tag => ["in1"]
  }
  # Measures the execution time of system2
  elapsed {
    unique_id_field => "messageId"
    start_tag => "system2Enter"
    end_tag => "system2Exit"
    new_event_on_match => true
    add_tag => ["in2"]
  }
  # Measures the time between system1 and system2
  elapsed {
    unique_id_field => "messageId"
    start_tag => "system1Exit"
    end_tag => "system2Enter"
    new_event_on_match => true
    add_tag => ["1->2"]
  }
  # Records the execution time of system1
  if "in1" in [tags] and "elapsed" in [tags] {
    aggregate {
      task_id => "%{messageId}"
      code => "map['report'] = [(event['elapsed_time']*1000).to_i]"
      map_action => "create"
    }
  }
  # Records the time between system1 and system2
  if "1->2" in [tags] and "elapsed" in [tags] {
    aggregate {
      task_id => "%{messageId}"
      code => "map['report'] << (event['elapsed_time']*1000).to_i"
      map_action => "update"
    }
  }
  # Records the execution time of system2
  if "in2" in [tags] and "elapsed" in [tags] {
    aggregate {
      task_id => "%{messageId}"
      code => "map['report'] << (event['elapsed_time']*1000).to_i; event['report'] = map['report'].join(':')"
      map_action => "update"
      end_of_task => true
    }
  }
}

После первых двух событий вы получите новое событие, которое показывает, что 197ms были потрачены в system1:

{
                 "@timestamp" => "2016-05-21T04:20:51.731Z",
                       "tags" => [ "elapsed", "elapsed_match", "in1" ],
               "elapsed_time" => 0.197,
                  "messageId" => "00e02f2f-32d5-9509-870a-f80e54dc8775",
    "elapsed_timestamp_start" => "2016-05-19T00:55:29.003Z"
}

И снова все кредиты отправляются автору исходного ответа:)

Ответ 4

Вы можете использовать scripted_metric для получения продолжительности. { "size": 0, "aggs": { "d_ids": { "terms": { "field": "name.keyword", "size": 10 }, "aggs": { "duration": { "scripted_metric": { "map_script": "if (doc.type.value == \"stop\") { params._agg.end = doc.eventTime.value; } else { params._agg.start = doc.eventTime.value; }", "reduce_script": "long start = 0; long end = 0; for(h in params._aggs) { if(h.start != null) { start = h.start; } if (h.end != null) { end = h.end; } } return (end - start);" } } } } } }

Вот ответ от вышеуказанного запроса: { "took": 1, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 4, "max_score": 0, "hits": [] }, "aggregations": { "d_ids": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "Device1", "doc_count": 2, "duration": { "value": 2700000 } }, { "key": "Device2", "doc_count": 2, "duration": { "value": 2880000 } } ] } } } Длительность в миллисекундах