Вычислите процент изменения скользящего временного окна в Elasticsearch

#elasticsearch

#elasticsearch

Вопрос:

Новичок в Elasticsearch здесь. У меня есть серия сообщений журнала, подобных этим

 {
  "@timestamp": "whatever",
  "type": "toBeMonitored",
  "success": true
}
  

Мне было поручено отреагировать на изменение -30% от общего количества успешных сообщений по сравнению со вчерашним тем же интервалом. Итак, если я выполню проверку сегодня в 8 утра, я должен сравнить сегодняшнее общее количество с полуночи до 8 утра со вчерашним тем же интервалом.

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

 {
  "size": 0, 
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "type": "toBeMonitored"
          }
        },
        {
          "term": {
            "status": true
          }
        },
        {
          "range": {
            "@timestamp": {
              "gte": "now-1d/d",
              "lte": "now/h"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "histo": {
       "date_histogram": {
        "field": "@timestamp",
        "fixed_interval": "1h"
      }
    }
  }
}
  

Есть идеи о том, как это можно сделать?

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

1. Лучше сделать это на стороне приложения.

Ответ №1:

Вы можете использовать derivative агрегацию конвейера для достижения именно того, чего вы ожидаете:

 POST /sales/_search
{
  "size": 0, 
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "type": "toBeMonitored"
          }
        },
        {
          "term": {
            "status": true
          }
        },
        {
          "range": {
            "@timestamp": {
              "gte": "now-1d/d",
              "lte": "now/h"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "histo": {
       "date_histogram": {
        "field": "@timestamp",
        "fixed_interval": "1h"
      },
      "aggs": {
        "successDiff": {
          "derivative": {
            "buckets_path": "_count"
          }
        }
      }
    }
  }
}
  

В каждом сегменте вы получите разницу между количеством документов в предыдущем сегменте и текущим сегментом.

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

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

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

3. Смотрите мой собственный ответ ниже

Ответ №2:

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

 {
  "size": 0,
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "type": "toBeMonitored"
          }
        },
        {
          "term": {
            "status": true
          }
        },
        {
          "range": {
            "@timestamp": {
              "gte": "now-1d/d",
              "lte": "now/h"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "ranged_documents": {
      "date_range": {
        "field": "@timestamp",
        "ranges": [
          {
            "key": "yesterday",
            "from": "now-1d/d",
            "to": "now-24h/h"
          },
          {
            "key": "today",
            "from": "now/d",
            "to": "now/h"
          }
        ],
        "keyed": true
      }
    }
  }
}

  

Этот запрос даст результат, аналогичный приведенному ниже

 {
    "_shards": {
        "total": 42,
        "failed": 0,
        "successful": 42,
        "skipped": 0
    },
    "hits": {
        "hits": [],
        "total": {
            "value": 10000,
            "relation": "gte"
        },
        "max_score": null
    },
    "took": 134,
    "timed_out": false,
    "aggregations": {
        "ranged_documents": {
            "buckets": {
                "yesterday": {
                    "from_as_string": "2020-10-12T00:00:00.000Z",
                    "doc_count": 268300,
                    "to_as_string": "2020-10-12T12:00:00.000Z",
                    "from": 1602460800000,
                    "to": 1602504000000
                },
                "today": {
                    "from_as_string": "2020-10-13T00:00:00.000Z",
                    "doc_count": 251768,
                    "to_as_string": "2020-10-13T12:00:00.000Z",
                    "from": 1602547200000,
                    "to": 1602590400000
                }
            }
        }
    }
}