TL;DR InfluxDB 技术提示 — 跨标签或字段聚合和取消分组

导航至

因此,您对时序数据库感兴趣,并且决定探索 InfluxDB Cloud 或 InfluxDB v2。也许您刚刚创建了一个免费帐户或下载了二进制文件,现在您正在使用 InfluxDB 用户界面 (UI) 并学习 Flux。初学者最难理解的是 Flux 查询或带注释的 CSV 的返回结果。本博客 TL;DR InfluxDB 技术提示 – 如何解释带注释的 CSV 中提供了带注释的 CSV 的详细说明,但今天我们将重点关注理解组键及其如何影响表流。换句话说,我们将学习

  • 如何使用示例数据集探索 Flux
  • 什么是组键,以及组键如何确定带注释的 CSV 输出中的表数量
  • 如何使用 group() Flux 函数更改组
  • 如何利用 group() 函数对数据进行分组和取消分组,从而跨字段或指标执行聚合

此 TL;DR 的 TL;DR:使用空的 group() Flux 函数取消分组数据

如果您已经熟悉上面部分中的要点,并且您只是想要以下问题的快速答案:您只想知道如何跨标签执行聚合,但您感到困惑,因为您的数据位于单独的表中。在执行聚合之前,将 |> group() 应用于您的 Flux 查询以取消分组数据。如果您仍然感到困惑,请继续阅读。

使用示例数据探索 Flux

开始使用 InfluxDB 的最简单方法是选择示例数据并使用 Flux 将其写入 InfluxDB。今天我们将使用 NOAA 水样本数据。此数据集相当大,因此我们将继续实际将数据写入我们的 InfluxDB 实例。为了写入数据,我们首先创建一个目标存储桶,用于存储我们的示例数据。您可以使用 InfluxDB UI 或 API创建一个新的存储桶

InfluxDB UI 中“加载数据”页面的屏幕截图<figcaption> InfluxDB UI 中加载数据页面的屏幕截图。</figcaption>

单击右侧菜单中的数据。然后导航到存储桶选项卡。最后,单击 + 创建存储桶以创建您的存储桶并命名。今天我们将我们的命名为“noaa”。

根据示例数据文档,我们将以下 Flux 代码复制并粘贴到 InfluxDB UI 中的脚本编辑器

import "experimental/csv"

relativeToNow = (tables=<-) =>
  tables
    |> elapsed()
    |> sort(columns: ["_time"], desc: true)
    |> cumulativeSum(columns: ["elapsed"])
    |> map(fn: (r) => ({ r with _time: time(v: int(v: now()) - (r.elapsed * 1000000000))}))

csv.from(url: "https://influx-testdata.s3.amazonaws.com/noaa.csv")
  |> relativeToNow()
  |> to(bucket: "noaa", org: "example-org")

InfluxDB UI 中脚本编辑器的屏幕截图 <figcaption> InfluxDB UI 中脚本编辑器的屏幕截图。</figcaption>

单击查询构建器按钮返回到查询构建器。单击提交按钮可让您运行 Flux 查询。

为了本 TL;DR 的目的,请忽略大部分 Flux。我们需要了解的是,您需要使用 to() 函数编辑最后一行

  • 将 bucket 参数替换为您的目标存储桶的名称。
  • 将 org 参数替换为您的组织的名称。在 InfluxDB Cloud 中,您的组织是您用于注册帐户的电子邮件。

组键及其如何确定带注释的 CSV 输出中的表数量

Data Explorer - Query Builder

使用查询构建器获取来自 santa_monica 和 coyote_creek 的 average_temperature 数据。打开查看原始数据(橙色)以查看带注释的 CSV 和组键。当该列中的值全部相同(绿色)或不同(粉红色)时,列将被分配一个真(此处以绿色突出显示)或假(粉红色)的组键注释值。

查询您的一些数据,然后将查看原始数据切换为“开”,以返回带注释的 CSV 输出。带注释的 CSV 输出是表流或表集合。组键定义表的大小和数量。组键注释是一个布尔值,用于确定列中的值在每一行中是否相同。具有值为 true 的组键注释的列是组键的一部分。

在上图中,我们查询了来自两个位置的平均温度数据。具体来说,我们查询了

  • 1 个指标,“average_temperature”。
  • 1 个字段,“degree”
  • 2 个“location”标签值,“coyote_creek”和“santa_monica”

这转换为以下 Flux 代码,如脚本编辑器所见。

from(bucket: "noaa")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "average_temperature")
|> filter(fn: (r) => r["_field"] == "degrees")
|> filter(fn: (r) => r["location"] == "coyote_creek" or r["location"] == "santa_monica")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|> yield(name: "mean")

我们的带注释的 CSV 输出的列包括

  • 表:此列按返回顺序为表流中的表分配一个数值。由于我们查询了两个标签值“coyote_creek”和“santa_monica”,我们将返回两个表。
  • _measurement:我们查询的数据的指标——“average_temperature”
  • _field:我们查询的数据的字段键——“degrees”
  • _value:数据字段值
  • _start:查询的开始日期
  • _stop:查询的停止日期
  • _time:时序的时间戳
  • location:我们查询的标签键

在这些列名下方是组键子标题。当列中的每一行都相同时,该列是组键的一部分。组键的一部分的列被赋予子标题“GROUP”,而从组键中排除的列被赋予子标题“NO GROUP”。

默认情况下,InfluxDB 将以下列作为组键的一部分包括在内

  • _measurement
  • _field
  • _start
  • _stop:查询的停止日期
  • 任何标签键列

默认情况下,这些列包含在组键中,以便为每个时序输出一个表。序列由指标、标签集和字段键的唯一组合定义。UI 将每个表绘制为单独的线条。

现在想象一下,您想找到两个位置的所有值的总和,因此您像这样添加 sum 函数

from(bucket: "noaa")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "average_temperature")
|> filter(fn: (r) => r["_field"] == "degrees")
|> filter(fn: (r) => r["location"] == "coyote_creek" or r["location"] == "santa_monica")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|> sum()

该查询将返回以下结果

query resultes

sum() 函数应用于 steam 中的每个表,因此我们最终得到每个位置的总和,而不是我们想要的结果:两个位置的总和。

为了纠正这一点,我们必须首先将 steam 中的两个表合并为一个表。有很多方法可以实现此目标,但最简单的方法是从组键中删除“location”列。应用一个空的 group() 函数而不传入任何列到该函数将有效地取消分组我们的数据。换句话说,以下 Flux 查询

from(bucket: "noaa")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "average_temperature")
|> filter(fn: (r) => r["_field"] == "degrees")
|> filter(fn: (r) => r["location"] == "coyote_creek" or r["location"] == "santa_monica")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
//limit is addded to visualize the results on one page
|> limit(n:3)
|> group()

生成以下带注释的 CSV 输出

Annotated CSV output

请注意,我们的两个表合并为一个表,并且没有列是组键的一部分。现在,如果我们在 Flux 查询的末尾添加 sum(),我们可以实现我们的初始目标并获得总和

Data Explorer - total sum

结论

我希望这篇 InfluxDB 博客文章有助于缓解围绕以下方面的一些困惑

  1.  什么是带注释的 CSV
  2.  组键如何影响表流输出
  3. 以及如何取消分组您的数据以在流中跨字段、标签和表执行聚合

如果您正在使用 InfluxDB v2 并且需要帮助,请在我们的社区站点Slack 频道中寻求帮助。如果您正在开发一个很酷的物联网应用程序或在 InfluxDB 之上监控您的应用程序,我们很乐意听到您的消息,因此请务必分享您的故事!此外,请在评论部分分享您的想法、疑虑或问题。我们很乐意获得您的反馈并帮助您解决遇到的任何问题!

延伸阅读

虽然这篇文章旨在全面概述如何跨字段、标签或表流进行聚合;以下资源也可能让您感兴趣

  1. TL;DR InfluxDB 技术提示 – 如何解释带注释的 CSV:这篇文章描述了如何解释带注释的 CSV,InfluxDB 的 Flux 查询结果格式。
  2. Python 和 InfluxDB v2.0 入门:这篇文章描述了如何开始使用 Python 客户端库。
  3. InfluxDB 和 Pandas 入门:这篇文章分享了如何开始使用 Pandas 将数据帧写入 InfluxDB 并使用 Flux 查询返回数据帧。
  4. Flux 初学者面临的 5 大障碍以及学习使用 Flux 的资源:这篇文章描述了 Flux 初学者面临的常见障碍,以及如何通过使用 InfluxDB UI、理解带注释的 CSV 等来解决这些障碍。
  5. Flux 中级用户面临的 5 大障碍以及优化 Flux 的资源:这篇文章描述了 Flux 中级和高级用户面临的常见障碍,同时更详细地介绍了下推模式、Flux 引擎的工作原理等等。