InfluxDB 2.0 を使う(2)　色々な値の取得を行う

# はじめに

[InfluxDB 2.0](https://www.influxdata.com/products/influxdb-overview/influxdb-2-0/)で、登録されたデータをCLIで取得する色々なやり方を見ていきます。

# 環境

* OS: Debian 9.11
* InfluxDB: v2.0.0-alpha.20

# サンプルデータの登録

はじめにサンプルデータをまとめてInfluxDBに登録しておきます。以下のファイルline-protocol.txtを用意します。2019-11-23の00:00～01:00の1時間の、1分おき60点のデータです。

```line-protocol.txt
my_measurement temperature=10.0 1574434800
my_measurement temperature=10.1 1574434860
my_measurement temperature=10.2 1574434920
my_measurement temperature=10.3 1574434980
my_measurement temperature=10.4 1574435040
my_measurement temperature=10.5 1574435100
my_measurement temperature=10.6 1574435160
my_measurement temperature=10.7 1574435220
my_measurement temperature=10.8 1574435280
my_measurement temperature=10.9 1574435340
my_measurement temperature=11.0 1574435400
my_measurement temperature=11.1 1574435460
my_measurement temperature=11.2 1574435520
my_measurement temperature=11.3 1574435580
my_measurement temperature=11.4 1574435640
my_measurement temperature=11.5 1574435700
my_measurement temperature=11.6 1574435760
my_measurement temperature=11.7 1574435820
my_measurement temperature=11.8 1574435880
my_measurement temperature=11.9 1574435940
my_measurement temperature=12.0 1574436000
my_measurement temperature=12.1 1574436060
my_measurement temperature=12.2 1574436120
my_measurement temperature=12.3 1574436180
my_measurement temperature=12.4 1574436240
my_measurement temperature=12.5 1574436300
my_measurement temperature=12.6 1574436360
my_measurement temperature=12.7 1574436420
my_measurement temperature=12.8 1574436480
my_measurement temperature=12.9 1574436540
my_measurement temperature=13.0 1574436600
my_measurement temperature=13.1 1574436660
my_measurement temperature=13.2 1574436720
my_measurement temperature=13.3 1574436780
my_measurement temperature=13.4 1574436840
my_measurement temperature=13.5 1574436900
my_measurement temperature=13.6 1574436960
my_measurement temperature=13.7 1574437020
my_measurement temperature=13.8 1574437080
my_measurement temperature=13.9 1574437140
my_measurement temperature=14.0 1574437200
my_measurement temperature=14.1 1574437260
my_measurement temperature=14.2 1574437320
my_measurement temperature=14.3 1574437380
my_measurement temperature=14.4 1574437440
my_measurement temperature=14.5 1574437500
my_measurement temperature=14.6 1574437560
my_measurement temperature=14.7 1574437620
my_measurement temperature=14.8 1574437680
my_measurement temperature=14.9 1574437740
my_measurement temperature=15.0 1574437800
my_measurement temperature=15.1 1574437860
my_measurement temperature=15.2 1574437920
my_measurement temperature=15.3 1574437980
my_measurement temperature=15.4 1574438040
my_measurement temperature=15.5 1574438100
my_measurement temperature=15.6 1574438160
my_measurement temperature=15.7 1574438220
my_measurement temperature=15.8 1574438280
my_measurement temperature=15.9 1574438340
```

サーバを起動し、同じホストから以下のコマンドでデータをまとめて登録します。

```
/influx write -p s @line-protocol.txt
```

# 時間の指定

[前記事](https://qiita.com/riverplus/items/5de5e830ddb622856209)でも述べた通り、データの取得を行うには、Fluxという言語でファイルにクエリを書き、`influx query`で実行します。

以下は指定時間のデータを取得するクエリです。時間の指定には`range`関数を用います。

```query1.flux
from(bucket: "my_bucket")
  |> range(start:2019-11-23T00:30:00+09:00, stop:2019-11-23T00:40:00+09:00)
```

実行結果は以下の通りです。00:30以降かつ00:40より前のデータ点が得られています。時刻がUTCで表されている点に注意して下さい。

```
$ ./influx query @query1.flux --org my_organization
Result: _result
Table: keys: [_start, _stop, _field, _measurement]
                   _start:time                      _stop:time           _field:string     _measurement:string                      _time:time                  _value:float  
------------------------------  ------------------------------  ----------------------  ----------------------  ------------------------------  ----------------------------  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:30:00.000000000Z                            13  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:31:00.000000000Z                          13.1  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:32:00.000000000Z                          13.2  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:33:00.000000000Z                          13.3  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:34:00.000000000Z                          13.4  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:35:00.000000000Z                          13.5  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:36:00.000000000Z                          13.6  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:37:00.000000000Z                          13.7  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:38:00.000000000Z                          13.8  
2019-11-22T15:30:00.000000000Z  2019-11-22T15:40:00.000000000Z             temperature          my_measurement  2019-11-22T15:39:00.000000000Z                          13.9  
```

# 平均値の取得

統計処理を施した結果を得ることができます。以下は、10分ごとの平均値を得るクエリです。

```query2.flux
from(bucket: "my_bucket")
  |> range(start:2019-11-23T00:00:00+09:00, stop:2019-11-23T01:00:00+09:00)
  |> aggregateWindow(every: 10m, fn: mean)
```

`range`で時間指定した結果に`aggregateWindow`関数をつなげます。結果は次のようになります。

```
$ ./influx query @query2.flux --org my_organization
Result: _result
Table: keys: [_start, _stop, _field, _measurement]
                   _start:time                      _stop:time           _field:string     _measurement:string                  _value:float                      _time:time  
------------------------------  ------------------------------  ----------------------  ----------------------  ----------------------------  ------------------------------  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         10.45  2019-11-22T15:10:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         11.45  2019-11-22T15:20:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         12.45  2019-11-22T15:30:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         13.45  2019-11-22T15:40:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         14.45  2019-11-22T15:50:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         15.45  2019-11-22T16:00:00.000000000Z 
```

`aggregateWindow`の引数では、`every`で時間間隔、`fn`で適用する関数を指定します。`fn`には平均値`mean`のほか、個数`count`や総和`sum`などが指定できます。詳細は[Aggregate functions](https://v2.docs.influxdata.com/v2.0/reference/flux/stdlib/built-in/transformations/aggregates/#aggregate-functions)を参照して下さい。

# オフセット付きでの平均値の取得

さらに複雑な処理を書くことができます。例えば以下は、時刻を5分ずつずらした10分ごとの平均値を求めるクエリです。つまり00:00～00:05, 00:05～00:15, 00:15～00:25, ・・の平均値を求めます。クエリの書き方は「[Window and aggregate data with Flux](https://v2.docs.influxdata.com/v2.0/query-data/guides/window-aggregate/)」の記事を全面的に参考にしています。

```query3.flux
from(bucket: "my_bucket")
  |> range(start: 2019-11-23T00:00:00+09:00, stop: 2019-11-23T01:00:00+09:00)
  |> window(every: 10m, offset: 5m)
  |> mean()
  |> duplicate(column: "_stop", as: "_time")
  |> window(every: inf)
```

結果は次のようになります。

```
$ ./influx query @query3.flux --org my_organization
Result: _result
Table: keys: [_start, _stop, _field, _measurement]
                   _start:time                      _stop:time           _field:string     _measurement:string                  _value:float                      _time:time  
------------------------------  ------------------------------  ----------------------  ----------------------  ----------------------------  ------------------------------  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                          10.2  2019-11-22T15:05:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         10.95  2019-11-22T15:15:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         11.95  2019-11-22T15:25:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         12.95  2019-11-22T15:35:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         13.95  2019-11-22T15:45:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                         14.95  2019-11-22T15:55:00.000000000Z  
2019-11-22T15:00:00.000000000Z  2019-11-22T16:00:00.000000000Z             temperature          my_measurement                          15.7  2019-11-22T16:00:00.000000000Z  
```

InfluxDB v1のクエリ言語InfluxQLでも、GROUP BY time()を使って一定時間ごとの平均値を求めることは可能でしたが、このようなオフセット付きでの計算は困難でした。Fluxの表現力はいろいろと有益そうです。（ちなみにFlux自体はInfluxDB v1でもv1.7以降で利用可能です。）

# おわりに

InfluxDB 2.0で登録されたデータを取得する色々なやり方を見ていきました。

# 参考

* [aggregateWindow() function](https://v2.docs.influxdata.com/v2.0/reference/flux/stdlib/built-in/transformations/aggregates/aggregatewindow/)