#time-series #influxdb #influxdb-2
#временные ряды #influxdb #influxdb-2
Вопрос:
TL; DR Я использую Influxdb версии 2.0 и использую синтаксис запроса Influx (как в графическом интерфейсе). У меня несколько рядов (одно и то же _field, другой тег) цифрового состояния 0/1, и я хочу их суммировать. Проблема в том, что состояние хранится в базе данных с нерегулярным временным интервалом, что означает, что в любое время реальное фактическое значение для каждого тега должно запрашиваться с последней возможной точкой. Я пробовал aggregateWindow с ‘last’ в качестве функции, но last просто отбрасывает таблицу для окон без сохранения точки. Могу ли я в любом случае их суммировать? Я принимаю любой метод (включая экспорт данных и использование другого языкового скрипта вместо lmao). Заранее благодарю вас.
Сценарий
Моя команда ранее внедрила систему регистрации заезда / отъезда с номером телефона, представляющим каждого человека для реального события, и решила использовать InfluxDB версии 2.0 в качестве базы данных (мы выбираем ее, чтобы мы могли легко отслеживать через Grafana). У меня есть корзина, в которой хранятся точки проверки / проверки значения, все по той же схеме. Схема выглядит следующим образом:
measurement: 'user'
tags: [phone, type] // type is either ['normal', 'staff']
value: 0 or 1 // 0 for checking out event, 1 for checking in event
Всякий раз, когда кто-то проверяет событие, вставляется точка со значением 1, и наоборот, точка со значением 0 вставляется всякий раз, когда кто-то проверяет событие. Имейте в виду, что точка может дублироваться, если пользователь решил снова запустить api, как если бы он уже зарегистрировался ранее и снова зарегистрировался (хотя мы рассматриваем это как имеющее то же состояние 1). Таким образом, данные похожи на цифровое состояние 0/1, но с нерегулярным временным интервалом точек, по одной строке графика для каждого телефонного номера. Одни и те же телефонные номера, но с разными типами, воспринимаются нами как разные люди.
Проект уже развернут, и нам поручено выполнить постобработку данных. Проблема заключается в визуализации графика совокупности событий за все время. С математической точки зрения это должно быть легко решено путем суммирования всех состояний каждого человека (строка 0/1) с течением времени. Я впервые попробовал что-то подобное в запросе Influx:
from(bucket: "event_name")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "user")
|> group(columns: ["type"])
|> aggregateWindow(every: v.windowPeriod, fn: sum, createEmpty: true)
|> yield()
Результат выглядит очень многообещающим, график населения с 2 цветами типа normal и staff . Но когда я внимательно смотрю, функция sum Influx фактически суммирует _value каждой точки в каждом окне. Это означает, что для некоторого окна без точки функция sum фактически не суммирует всех в базе данных. Цель состоит в том, чтобы суммировать фактическое _value для тех окон, в которых нет точки (_value этого окна должно совпадать с _value последней точки, например. как я зарегистрировался в 7:00вечера, а _value должно быть 1 все время после 7:00 вечера, даже в каком-то окне нет точки).любая точка). Затем я попробовал что-то вроде этого:
from(bucket: "event_name")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "user")
|> aggregateWindow(every: 1m, fn: last, createEmpty: true)
|> fill(usePrevious: true)
|> group(columns: ["type"])
|> aggregateWindow(every: 1m, fn: sum)
|> yield()
Я использую последнюю точку для каждого окна, затем заполняю окно пустым _value с предыдущей возможной точкой, затем снова суммирую _value каждого окна. Но потом я обнаружил, что last
функция фактически удаляет пустую таблицу, что означает, что окно без точки отбрасывается (createEmpty тогда бесполезно). Затем проблема заключается в том, что я должен найти функцию, подобную last
, но без удаления пустой таблицы. Я пытался reduce
создать свою собственную логику, last
но, к сожалению, все пошло не так, как я хочу (возможно, я неправильно ее закодировал).
Если у вас есть какие-либо идеи, пожалуйста, помогите. Большое вам спасибо.
Ответ №1:
Nvm, я нашел решение, вот для тех, кто прав в той же ситуации, хотя и не очень элегантно по производительности, но это единственный запрос, который я нашел, он работает.
from(bucket: "event_name")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "user")
|> aggregateWindow(every: 1m, fn: last, createEmpty: false)
|> aggregateWindow(every: 1m, fn: mean, createEmpty: true)
|> fill(usePrevious: true)
|> fill(value: 0.0)
|> group(columns: ["type"])
|> aggregateWindow(every: 1m, fn: sum, createEmpty: false)
|> yield(name: "population")
- Я использую
last
first, чтобы иметь последнее состояние для каждого окна (хотяlast
на самом деле отбрасываю пустые таблицы, поэтому созданиеcreateEmpty: true
в любом случае бесполезно) - Затем для окон, в которых нет точки, я использую
mean
withcreateEmpty: true
, чтобы создавать точки с null_value
для пустых окон. Для окон, которые на самом деле имеют реальные точки,mean
не следует изменять значение, поскольку в окне должно быть только 1 точка, потому что мы использовалиlast
ранее. Смысл использованияmean
здесь заключается только в создании нулевых точек для пустых окон. Здесь нужно просто найти ничего не делающую функцию, которая не удаляет пустую таблицу, созданнуюcreateEmpty
. К вашему сведению, я перепробовал много функций, включая создание собственной пользовательской функции, подобнойreduce
andmap
, но они отбрасывают пустые таблицы (а присвоение null даже не разрешено), я даже создаю пустую функцию, подобнуюfn: (tables=<-, x) => tables
foraggregateWindow
, но она все равно отбрасывает пустые таблицы. Такmean
что мой лучший выбор здесь, хотя побочный эффект заключается в том, что мои значения меняются с int на float. - Я использую
fill
здесь для замены нулевых точек значением из последнего окна. Вот почему я пытаюсь присвоить null точке в пустых окнах с последнего шага иmean
могу только это. Второеfill
— для тех ранних пустых окон, которые должны представлять 0-состояние. - Затем по типу и их сопоставлению должен быть результат, который я ищу
group
sum
Надеюсь, я смогу помочь всем, кто в будущем окажется в такой же ситуации, как я
Комментарии:
1. Я сталкиваюсь с той же проблемой, и мне интересно, не лучше ли нам использовать InfluxQL?
2. Я согласен, нам должно быть лучше с InfluxQL. Документ и синтаксис на самом деле недостаточно отшлифованы. Даже сама InfluxDB версии 2.0 тоже не очень удобна, например, почему я должен устанавливать ее как сервис в systemctl, когда версия 1.8 в этом не нуждается (и в документации об этом тоже не упоминается). Я думаю, эта версия v2.0 просто не для новичков.