ElasticSearch / Kibana: получить значения, которые не найдены в записях, более поздних, чем определенная дата - PullRequest
1 голос
/ 09 апреля 2020

У меня есть парк устройств, которые регулярно отправляют в ElasticSearch (скажем, каждые 10 минут) записи этой формы:

{
    "deviceId": "unique-device-id",
    "timestamp": 1586390031,
    "payload" : { various data }
}

Обычно я просматриваю это через Кибану, фильтруя данные за последние 7 дней, а затем детализация по идентификатору устройства или какой-либо другой части данных из полезной нагрузки.

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

Я мечтаю, чтобы в приведенной выше таблице содержались только идентификаторы устройств, о которых не сообщалось в последний час, или получить только два числа: общее количество различных идентификаторов устройств, увиденных за последние 7 дней, и общее количество идентификаторов устройств, не замеченных за последний час.

Можете ли вы указать мне правильное направление, если таковое имеется одно из них вообще возможно?

1 Ответ

1 голос
/ 10 апреля 2020

Я пропущу стол и воспользуюсь вторым подходом - получаю только счет. Я думаю, что можно идти назад к строкам из отсчетов.


Примечание: я буду использовать удобочитаемый формат времени вместо отметок времени, но epoch_seconds будет работать просто как хорошо в вашем реальном случае использования. Кроме того, я добавил поле comment, чтобы дать каждому фону c некоторый фон.

Сначала настройте свой индекс:

PUT fleet
{
  "mappings": {
    "properties": {
      "timestamp": {
        "type": "date",
        "format": "epoch_second||yyyy-MM-dd HH:mm:ss"
      },
      "comment": {
        "type": "text"
      },
      "deviceId": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

Syn c несколько документов - я в UTC + 2, поэтому я выбрал следующие временные метки:

POST fleet/_doc
{
  "deviceId": "asdjhfa343",
  "timestamp": "2020-04-05 10:00:00",
  "comment": "in the last week"
}

POST fleet/_doc
{
  "deviceId": "asdjhfa343",
  "timestamp": "2020-04-10 13:05:00",
  "comment": "#asdjhfa343 in the last hour"
}

POST fleet/_doc
{
  "deviceId": "asdjhfa343",
  "timestamp": "2020-04-10 12:05:00",
  "comment": "#asdjhfa343 in the 2 hours"
}

POST fleet/_doc
{
  "deviceId": "asdjhfa343sdas",
  "timestamp": "2020-04-07 09:00:00",
  "comment": "in the last week"
}

POST fleet/_doc
{
  "deviceId": "asdjhfa343sdas",
  "timestamp": "2020-04-10 12:35:00",
  "comment": "in last 2hrs"
}

В общей сложности у нас есть 5 документов и 2 разных идентификатора устройства со следующими условиями

  1. все они появились за последние 7d
  2. , оба из которых за последние 2 часа и
  3. только один из которых за последний час

поэтому мне интересно найти именно 1 deviceId, который появился в последние 2 часа, НО не последний 1 час .

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

GET fleet/_search
{
  "size": 0,
  "aggs": {
    "distinct_devices_last7d": {
      "filter": {
        "range": {
          "timestamp": {
            "gte": "now-7d"
          }
        }
      },
      "aggs": {
        "uniq_device_count": {
          "cardinality": {
            "field": "deviceId.keyword"
          }
        }
      }
    },
    "not_seen_last1h": {
      "filter": {
        "range": {
          "timestamp": {
            "gte": "now-2h"
          }
        }
      },
      "aggs": {
        "device_ids_per_hour": {
          "date_histogram": {
            "field": "timestamp",
            "calendar_interval": "day",
            "format": "'disregard' -- yyyy-MM-dd"
          },
          "aggs": {
            "total_uniq_count": {
              "cardinality": {
                "field": "deviceId.keyword"
              }
            },
            "in_last_hour": {
              "filter": {
                "range": {
                  "timestamp": {
                    "gte": "now-1h"
                  }
                }
              },
              "aggs": {
                "uniq_count": {
                  "cardinality": {
                    "field": "deviceId.keyword"
                  }
                }
              }
            },
            "uniq_difference": {
              "bucket_script": {
                "buckets_path": {
                  "in_last_1h": "in_last_hour>uniq_count",
                  "in_last2h": "total_uniq_count"
                },
                "script": "params.in_last2h - params.in_last_1h"
              }
            }
          }
        }
      }
    }
  }
}

Агрегация date_histogram - это просто заполнитель, который позволяет нам использовать bucket script для получения окончательной разницы и не выполнять никакой постобработки.

Поскольку мы прошло size: 0, нас не интересует раздел hits. Итак, принимая только агрегации, вот аннотированные результаты:

...
"aggregations" : {
    "not_seen_last1h" : {
      "doc_count" : 3,
      "device_ids_per_hour" : {
        "buckets" : [
          {
            "key_as_string" : "disregard -- 2020-04-10",
            "key" : 1586476800000,
            "doc_count" : 3,            <-- 3 device messages in the last 2hrs
            "total_uniq_count" : {
              "value" : 2               <-- 2 distinct IDs
            },
            "in_last_hour" : {
              "doc_count" : 1,
              "uniq_count" : {
                "value" : 1             <-- 1 distict ID in the last hour
              }
            },
            "uniq_difference" : {
              "value" : 1.0             <-- 1 == final result !
            }
          }
        ]
      }
    },
    "distinct_devices_last7d" : {
      "meta" : { },
      "doc_count" : 5,                  <-- 5 device messages in the last 7d
      "uniq_device_count" : {
        "value" : 2                     <-- 2 unique IDs
      }
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...