1

TL;DR 我正在使用 Influxdb v2.0 并使用 Influx 查询语法(如在 GUI 中)。我有多个数字 0/1 状态的系列(相同的_field,不同的标签),我想总结一下。问题是状态以不规则的时间间隔存储在数据库中,这意味着任何时候都应该使用最后一个点来查询每个标签的实际值。我已经尝试使用“last”作为函数的聚合窗口,但最后只是为没有存储点的窗口删除表。无论如何我可以总结它们吗?我接受任何方法(包括导出数据并使用其他语言脚本代替 lmao)。先感谢您。


情景

我的团队早些时候实施了一个登记/退房系统,电话号码代表每个人的真实世界事件,并决定使用 InfluxDB v2.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 种颜色类型的正常和人员。但是仔细看,Influx 的 sum 函数实际上是对每个窗口中每个点的 _value 求和。这意味着对于一些没有意义的窗口,sum 函数实际上并没有总结数据库中的每个人。目标是对那些没有点的窗口的实际 _value 求和(这些窗口的 _value 应该与最后一个点的 _value 相同,例如,就像我在晚上 7 点签到并且 _value 应该是 1 所有晚上 7 点之后的时间,即使某些窗口也没有任何意义)。然后我尝试了这样的事情:

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但遗憾的是它并没有像我想要的那样进行(可能是我编码错误)。

如果您有任何想法,请提供帮助。非常感谢。

4

1 回答 1

3

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")
  1. last首先使用每个窗口的最新状态(尽管last实际上删除了空表,所以createEmpty: true无论如何制作都没用)
  2. 然后对于没有任何点的窗口,我使用meanwith来为空窗口createEmpty: true创建带有 null 的点。_value对于实际上有实际点的窗口,mean不应更改该值,因为每个窗口应该只有 1 个点,因为我们之前使用last过。这里使用mean的目的只是为空窗口创建空点。这里的步骤只是找到一个不做任何事情的函数,它不会删除由createEmpty. 仅供参考,我尝试了许多功能,包括制作我自己的自定义函数reducemap但它们确实删除了空表(甚至不允许分配 null),我什至创建了一个类似fn: (tables=<-, x) => tablesforaggregateWindow但它仍然删除空表的空函数。所以mean是我最好的选择,尽管副作用是我的值从 int 变为 float。
  3. fill在这里使用最后一个窗口中的值替换空点。这就是为什么我试图从最后一步将 null 分配给空窗口中的点,并且mean只能这样做。第二个fill是那些应该代表0状态的早期空窗口。
  4. 然后group按类型并sum整理它们应该是我要寻找的结果

希望以后能帮到和我一样情况的人

于 2020-11-08T13:49:22.557 回答