Query data with Flux

The following guides walk through both common and complex queries and use cases for Flux.

Example data variable

Many of the examples provided in the following guides use a data variable, which represents a basic query that filters data by measurement and field. data is defined as:

  1. data = from(bucket: "db/rp")
  2. |> range(start: -1h)
  3. |> filter(fn: (r) =>
  4. r._measurement == "example-measurement" and
  5. r._field == "example-field"
  6. )

Flux query guides


Execute Flux queries

Use the InfluxDB CLI, API, and the Chronograf Data Explorer to execute Flux queries.

Query fields and tags

Use the filter() function to query data based on fields, tags, or any other column value. filter() performs operations similar to the SELECT statement and the WHERE clause in InfluxQL and other SQL-like query languages.

  1. from(bucket: "db/rp")
  2. |> range(start: -1h)
  3. |> filter(fn: (r) =>
  4. r._measurement == "example-measurement" and
  5. r._field == "example-field" and
  6. r.tag == "example-tag"
  7. )

Group

Use the group() function to group data with common values in specific columns.

  1. data
  2. |> group(columns: ["host"], mode: "by")
Input:
_timehost_value
2020-01-01T00:01:00Zhost11.0
2020-01-01T00:01:00Zhost22.0
2020-01-01T00:02:00Zhost11.0
2020-01-01T00:02:00Zhost23.0
Output:
_timehost_value
2020-01-01T00:01:00Zhost11.0
2020-01-01T00:02:00Zhost11.0
_timehost_value
2020-01-01T00:01:00Zhost22.0
2020-01-01T00:02:00Zhost23.0

Sort and limit

Use the sort()function to order records within each table by specific columns and the limit() function to limit the number of records in output tables to a fixed number, n.

  1. data
  2. |> sort(columns: ["host", "_value"])
  3. |> limit(n: 4)
Input:
_timehost_value
2020-01-01T00:01:00ZA1.0
2020-01-01T00:02:00ZB1.2
2020-01-01T00:03:00ZA1.8
2020-01-01T00:04:00ZB0.9
2020-01-01T00:05:00ZB1.4
2020-01-01T00:06:00ZB2.0
Output:
_timehost_value
2020-01-01T00:03:00ZA1.8
2020-01-01T00:01:00ZA1.0
2020-01-01T00:06:00ZB2.0
2020-01-01T00:05:00ZB1.4

Window & aggregate

This guide walks through windowing and aggregating data with Flux and outlines how it shapes your data in the process.

  1. data
  2. |> aggregateWindow(every: 20m, fn: mean)
Input:
_time_value
2020-01-01T00:00:00Z250
2020-01-01T00:04:00Z160
2020-01-01T00:12:00Z150
2020-01-01T00:19:00Z220
2020-01-01T00:32:00Z200
2020-01-01T00:51:00Z290
2020-01-01T01:00:00Z340
Output:
_time_value
2020-01-01T00:20:00Z195
2020-01-01T00:40:00Z200
2020-01-01T01:00:00Z290
2020-01-01T01:20:00Z340

Transform data with math

Use the map() function to remap column values and apply mathematic operations.

  1. data
  2. |> map(fn: (r) => ({ r with _value: r._value * r._value }))
Input:
_time_value
2020-01-01T00:01:00Z2
2020-01-01T00:02:00Z4
2020-01-01T00:03:00Z3
2020-01-01T00:04:00Z5
Output:
_time_value
2020-01-01T00:01:00Z4
2020-01-01T00:02:00Z16
2020-01-01T00:03:00Z9
2020-01-01T00:04:00Z25

Calculate percentages

Use pivot() or join() and the map() function to align operand values into rows and calculate a percentage.

  1. data
  2. |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  3. |> map(fn: (r) => ({
  4. _time: r._time,
  5. _field: "used_percent",
  6. _value: float(v: r.used) / float(v: r.total) * 100.0
  7. }))
Input:
_time_field_value
2020-01-01T00:00:00Zused2.5
2020-01-01T00:00:10Zused3.1
2020-01-01T00:00:20Zused4.2
_time_field_value
2020-01-01T00:00:00Ztotal8.0
2020-01-01T00:00:10Ztotal8.0
2020-01-01T00:00:20Ztotal8.0
Output:
_time_field_value
2020-01-01T00:00:00Zused_percent31.25
2020-01-01T00:00:10Zused_percent38.75
2020-01-01T00:00:20Zused_percent52.50

Increase

Use the increase() function to track increases across multiple columns in a table. This function is especially useful when tracking changes in counter values that wrap over time or periodically reset.

  1. data
  2. |> increase()
Input:
_time_value
2020-01-01T00:01:00Z1
2020-01-01T00:02:00Z2
2020-01-01T00:03:00Z8
2020-01-01T00:04:00Z10
2020-01-01T00:05:00Z0
2020-01-01T00:06:00Z4
Output:
_time_value
2020-01-01T00:02:00Z1
2020-01-01T00:03:00Z7
2020-01-01T00:04:00Z9
2020-01-01T00:05:00Z9
2020-01-01T00:06:00Z13

Moving Average

Use the movingAverage() or timedMovingAverage() functions to return the moving average of data.

  1. data
  2. |> movingAverage(n: 5)
Input:
_time_value
2020-01-01T00:01:00Z1.0
2020-01-01T00:02:00Z1.2
2020-01-01T00:03:00Z1.8
2020-01-01T00:04:00Z0.9
2020-01-01T00:05:00Z1.4
2020-01-01T00:06:00Z2.0
Output:
_time_value
2020-01-01T00:03:00Z1.33
2020-01-01T00:04:00Z1.30
2020-01-01T00:05:00Z1.36
2020-01-01T00:06:00Z1.43
  1. data
  2. |> timedMovingAverage(every: 2m, period: 4m)
Input:
_time_value
2020-01-01T00:01:00Z1.0
2020-01-01T00:02:00Z1.2
2020-01-01T00:03:00Z1.8
2020-01-01T00:04:00Z0.9
2020-01-01T00:05:00Z1.4
2020-01-01T00:06:00Z2.0
Output:
_time_value
2020-01-01T00:02:00Z1.000
2020-01-01T00:04:00Z1.333
2020-01-01T00:06:00Z1.325
2020-01-01T00:06:00Z1.150

Rate

Use the derivative() function to calculate the rate of change between subsequent values or the aggregate.rate() function to calculate the average rate of change per window of time. If time between points varies, these functions normalize points to a common time interval making values easily comparable.

  1. data
  2. |> derivative(unit: 1m, nonNegative: true)
Input:
_time_value
2020-01-01T00:00:00Z250
2020-01-01T00:04:00Z160
2020-01-01T00:12:00Z150
2020-01-01T00:19:00Z220
2020-01-01T00:32:00Z200
2020-01-01T00:51:00Z290
2020-01-01T01:00:00Z340
Output:
_time_value
2020-01-01T00:04:00Z
2020-01-01T00:12:00Z
2020-01-01T00:19:00Z10.0
2020-01-01T00:32:00Z
2020-01-01T00:51:00Z4.74
2020-01-01T01:00:00Z5.56
  1. import "experimental/aggregate"
  2. data
  3. |> aggregate.rate(every: 20m, unit: 1m)
Input:
_time_value
2020-01-01T00:00:00Z250
2020-01-01T00:04:00Z160
2020-01-01T00:12:00Z150
2020-01-01T00:19:00Z220
2020-01-01T00:32:00Z200
2020-01-01T00:51:00Z290
2020-01-01T01:00:00Z340
Output:
_time_value
2020-01-01T00:20:00Z
2020-01-01T00:40:00Z10.0
2020-01-01T01:00:00Z4.74
2020-01-01T01:20:00Z5.56

Histograms

Use the histogram() function to create cumulative histograms with Flux.

  1. data
  2. |> histogram(
  3. column: "_value",
  4. upperBoundColumn: "le",
  5. countColumn: "_value",
  6. bins: [100.0, 200.0, 300.0, 400.0],
  7. )
Input:
_time_value
2020-01-01T00:00:00Z250.0
2020-01-01T00:01:00Z160.0
2020-01-01T00:02:00Z150.0
2020-01-01T00:03:00Z220.0
2020-01-01T00:04:00Z200.0
2020-01-01T00:05:00Z290.0
2020-01-01T01:00:00Z340.0
Output:
le_value
100.00.0
200.03.0
300.06.0
400.07.0

Fill

Use the fill() function to replace null values.

  1. data
  2. |> fill(usePrevious: true)
Input:
_time_value
2020-01-01T00:01:00Znull
2020-01-01T00:02:00Z0.8
2020-01-01T00:03:00Znull
2020-01-01T00:04:00Znull
2020-01-01T00:05:00Z1.4
Output:
_time_value
2020-01-01T00:01:00Znull
2020-01-01T00:02:00Z0.8
2020-01-01T00:03:00Z0.8
2020-01-01T00:04:00Z0.8
2020-01-01T00:05:00Z1.4
  1. data
  2. |> fill(value: 0.0)
Input:
_time_value
2020-01-01T00:01:00Znull
2020-01-01T00:02:00Z0.8
2020-01-01T00:03:00Znull
2020-01-01T00:04:00Znull
2020-01-01T00:05:00Z1.4
Output:
_time_value
2020-01-01T00:01:00Z0.0
2020-01-01T00:02:00Z0.8
2020-01-01T00:03:00Z0.0
2020-01-01T00:04:00Z0.0
2020-01-01T00:05:00Z1.4

Median

Use the median() function to return a value representing the 0.5 quantile (50th percentile) or median of input data.

  1. data
  2. |> median()
Input:
_time_value
2020-01-01T00:01:00Z1.0
2020-01-01T00:02:00Z1.0
2020-01-01T00:03:00Z2.0
2020-01-01T00:04:00Z3.0
Output:
_value
1.5

Percentile & quantile

Use the quantile() function to return all values within the q quantile or percentile of input data.

  1. data
  2. |> quantile(q: 0.99, method: "estimate_tdigest")
Input:
_time_value
2020-01-01T00:01:00Z1.0
2020-01-01T00:02:00Z1.0
2020-01-01T00:03:00Z2.0
2020-01-01T00:04:00Z3.0
Output:
_value
3.0

Join

This guide walks through joining data with Flux and outlines how it shapes your data in the process.

  1. t1 = from(bucket: "example-bucket")
  2. |> range(start: 2020-01-01T00:00:00Z)
  3. |> filter(fn: (r) => r.m == "foo")
  4. t2 = from(bucket: "example-bucket")
  5. |> range(start: 2020-01-01T00:00:00Z)
  6. |> filter(fn: (r) => r.m == "bar")
  7. join(tables: {t1: t1, t2: t2}, on: ["_time"])
Input:
t1
_time_value
2020-01-01T00:01:00Z1
2020-01-01T00:02:00Z2
2020-01-01T00:03:00Z1
2020-01-01T00:04:00Z3
t2
_time_value
2020-01-01T00:01:00Z5
2020-01-01T00:02:00Z2
2020-01-01T00:03:00Z3
2020-01-01T00:04:00Z4
Output:
_time_value_t1_value_t2
2020-01-01T00:01:00Z15
2020-01-01T00:02:00Z22
2020-01-01T00:03:00Z13
2020-01-01T00:04:00Z34

Cumulative sum

Use the cumulativeSum() function to calculate a running total of values.

  1. data
  2. |> cumulativeSum()
Input:
_time_value
2020-01-01T00:01:00Z1
2020-01-01T00:02:00Z2
2020-01-01T00:03:00Z1
2020-01-01T00:04:00Z3
Output:
_time_value
2020-01-01T00:01:00Z1
2020-01-01T00:02:00Z3
2020-01-01T00:03:00Z4
2020-01-01T00:04:00Z7

First and last

Use the first() or last() functions to return the first or last point in an input table.

  1. data
  2. |> first()
Input:
_time_value
2020-01-01T00:01:00Z1.0
2020-01-01T00:02:00Z1.0
2020-01-01T00:03:00Z2.0
2020-01-01T00:04:00Z3.0
Output:
_time_value
2020-01-01T00:01:00Z1.0
  1. data
  2. |> last()
Input:
_time_value
2020-01-01T00:01:00Z1.0
2020-01-01T00:02:00Z1.0
2020-01-01T00:03:00Z2.0
2020-01-01T00:04:00Z3.0
Output:
_time_value
2020-01-01T00:04:00Z3.0

Exists

Use the Flux exists operator to check if a record contains a key or if that key’s value is null.

Filter null values
  1. data
  2. |> filter(fn: (r) => exists r._value)

Extract scalar values

Use Flux stream and table functions to extract scalar values from Flux query output. This lets you, for example, dynamically set variables using query results.

  1. scalarValue = {
  2. _record =
  3. data
  4. |> tableFind(fn: key => true)
  5. |> getRecord(idx: 0)
  6. return _record._value
  7. }

Manipulate timestamps

Use Flux to process and manipulate timestamps.

Monitor states

Flux provides several functions to help monitor states and state changes in your data.

Query SQL data

The Flux sql package provides functions for working with SQL data sources. Use sql.from() to query SQL databases like PostgreSQL and MySQL

  1. import "sql"
  2. sql.from(
  3. driverName: "postgres",
  4. dataSourceName: "postgresql://user:password@localhost",
  5. query: "SELECT * FROM example_table"
  6. )

Conditional logic

This guide describes how to use Flux conditional expressions, such as if, else, and then, to query and transform data. Flux evaluates statements from left to right and stops evaluating once a condition matches.

  1. if color == "green" then "008000" else "ffffff"

Regular expressions

This guide walks through using regular expressions in evaluation logic in Flux functions.

  1. data
  2. |> filter(fn: (r) => r.tag =~ /^foo[1-3]/)
Input:
_timetag_value
2020-01-01T00:01:00Zfoo11.0
2020-01-01T00:02:00Zfoo51.2
2020-01-01T00:03:00Zbar31.8
2020-01-01T00:04:00Zfoo30.9
2020-01-01T00:05:00Zfoo21.4
2020-01-01T00:06:00Zbar12.0
Output:
_timetag_value
2020-01-01T00:01:00Zfoo11.0
2020-01-01T00:04:00Zfoo30.9
2020-01-01T00:05:00Zfoo21.4

Geo-temporal data

Use the Flux Geo package to filter geo-temporal data and group by geographic location or track.

  1. import "experimental/geo"
  2. sampleGeoData
  3. |> geo.filterRows(region: {lat: 30.04, lon: 31.23, radius: 200.0})
  4. |> geo.groupByArea(newColumn: "geoArea", level: 5)

Optimize Flux queries

Optimize your Flux queries to reduce their memory and compute (CPU) requirements.

Use Flux in Chronograf dashboards

This guide walks through using Flux queries in Chronograf dashboard cells, what template variables are available, and how to use them.