# Flux — full Markdown corpus > Generated 2026-10-31T04:19:00.606Z from https://docs.influxdata.com/flux/v0/ > See https://docs.influxdata.com/llms.txt for the cross-product table of contents. > Publisher: InfluxData (https://www.influxdata.com) > sameAs: https://github.com/influxdata, https://hub.docker.com/u/influxdata, https://www.crunchbase.com/organization/influxdb, https://www.linkedin.com/company/influxdb, https://twitter.com/influxdb, https://www.youtube.com/@InfluxData, https://www.facebook.com/influxdb/ --- # Flux documentation Source: https://docs.influxdata.com/flux/v0/ Flux is an open source functional data scripting language designed for querying, analyzing, and acting on data. Flux supports multiple data source types, including: * Time series databases (such as [InfluxDB](/flux/v0/query-data/influxdb/)) * [Relational SQL databases](/flux/v0/query-data/sql/)(such as [MySQL](/flux/v0/query-data/sql/mysql/) and [PostgreSQL](/flux/v0/query-data/sql/postgresql/)) * [CSV](/flux/v0/query-data/csv/) Flux unifies code for querying, processing, writing, and acting on data into a single syntax. The language is designed to be usable, readable, flexible, composable, testable, contributable, and shareable. [Get started with Flux](/flux/v0/get-started/) --- # Work with Flux data types Source: https://docs.influxdata.com/flux/v0/data-types/ A Flux **data type** defines the set of possible values and operations. Flux is **statically typed**, meaning data types are never explicitly declared as part of the Flux syntax (except as part of a [builtin statement](/flux/v0/spec/system-built-ins/)) and types are inferred from how a variable is used. Flux data types are organized into the following: ## [Basic types](/flux/v0/data-types/basic/) All Flux data types are constructed from **basic types**: boolean, bytes, duration, string, time, float, integer, uintegers, and null. ## [Composite types](/flux/v0/data-types/composite/) Flux **composite types** are types constructed from basic types. Flux supports the following composite types: record, array, dictionary, function. ## [Dynamic types](/flux/v0/data-types/dynamic/) A **dynamic** type is a wrapper for data whose type is not known until runtime. Dynamic types help when working with data from external sources (like JSON) that support types that do not have an equivalent Flux type. --- # Work with basic data types Source: https://docs.influxdata.com/flux/v0/data-types/basic/ All Flux data types are constructed from the following **basic types**: * [Boolean](#boolean) * [Bytes](#bytes) * [Duration](#duration) * [Regular expression](#regular-expression) * [String](#string) * [Time](#time) * [Float](#float) * [Integer](#integer) * [UIntegers](#uintegers) * [Null](#null) ### [Boolean](/flux/v0/data-types/basic/bool/) A **boolean** type represents a truth value (`true` or `false`). Learn how to work with boolean data types in Flux. ```js true false ``` [Read more ](/flux/v0/data-types/basic/bool/) ### [Bytes](/flux/v0/data-types/basic/bytes/) A **bytes** type represents a sequence of byte values. Learn how to work with bytes data types in Flux. ### [Duration](/flux/v0/data-types/basic/duration/) A **duration** type represents a length of time with nanosecond precision Learn how to work with duration data types in Flux. ``` 1ns 1h 1w 3d12h4m25s ``` [Read more ](/flux/v0/data-types/basic/duration/) ### [Regular expression](/flux/v0/data-types/basic/regexp/) A **regular expression** type represents a regular expression pattern. Learn how to work with Flux regular expression types. ```js /^[a-z0-9]+$/ ``` [Read more ](/flux/v0/data-types/basic/regexp/) ### [String](/flux/v0/data-types/basic/string/) A **string** type represents a sequence of characters. Learn how to work with string data types in Flux. ```js "abc" "string with double \" quote" "string with backslash \\" "日本語" "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" ``` [Read more ](/flux/v0/data-types/basic/string/) ### [Time](/flux/v0/data-types/basic/time/) A **time** type represents a single point in time with nanosecond precision. Learn how to work with time data types in Flux. ```js 2021-01-01 2021-01-01T00:00:00Z 2021-01-01T00:00:00.000Z ``` [Read more ](/flux/v0/data-types/basic/time/) ### [Float](/flux/v0/data-types/basic/float/) A **float** type represents a [IEEE-754](https://standards.ieee.org/standard/754-2019.html) 64-bit floating-point number. Learn how to work with float types in Flux. ```js 0.0 123.4 -123.456 ``` [Read more ](/flux/v0/data-types/basic/float/) ### [Integer](/flux/v0/data-types/basic/int/) An **integer** type represents a signed 64-bit integer. Learn how to work with integer types in Flux. ```js 0 2 1254 -1254 ``` [Read more ](/flux/v0/data-types/basic/int/) ### [UIntegers](/flux/v0/data-types/basic/uint/) An **unsigned integer** (uinteger) type represents a unsigned 64-bit integer. Learn how to work with unsigned integer types in Flux. ```js uint(v: 123) ``` [Read more ](/flux/v0/data-types/basic/uint/) ### [Null](/flux/v0/data-types/basic/null/) The **null type** represents a missing or unknown value. Learn how to work with null types in Flux. --- # Work with booleans Source: https://docs.influxdata.com/flux/v0/data-types/basic/bool/ A **boolean** type represents a truth value (`true` or `false`). **Type name**: `bool` * [Boolean syntax](#boolean-syntax) * [Convert data types to booleans](#convert-data-types-to-booleans) * [Negate boolean values](#negate-boolean-values) ## Boolean syntax Boolean literals are represented by the following: ```js true false ``` ## Convert data types to booleans Use the [`bool()` function](/flux/v0/stdlib/universe/bool/) to convert the following [basic types](/flux/v0/data-types/basic/) to booleans: * **string**: value must be `"true"` or `"false"`. * **float**: value must be `0.0` (false) or `1.0` (true). * **int**: value must be `0` (false) or `1` (true). * **uint**: value must be `0` (false) or `1` (true). ``` bool(v: "true") // Returns true bool(v: 0.0) // Returns false bool(v: 0) // Returns false bool(v: uint(v: 1)) // Returns true ``` ### Convert columns to booleans Flux lets you iterate over rows in a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)and convert columns to booleans. **To convert the `_value` column to booleans**, use the [`toBool()` function](/flux/v0/stdlib/universe/bool/). > [!Note] > `toBool()` only operates on the `_value` column. ```js data |> toBool() ``` ##### Given the following input data: | \_time |\_value *(float)*| |--------------------|-----------------| |2021-01-01T00:00:00Z| 1.0 | |2021-01-01T02:00:00Z| 0.0 | |2021-01-01T03:00:00Z| 0.0 | |2021-01-01T04:00:00Z| 1.0 | ##### The example above returns: | \_time |\_value *(bool)*| |--------------------|----------------| |2021-01-01T00:00:00Z| true | |2021-01-01T02:00:00Z| false | |2021-01-01T03:00:00Z| false | |2021-01-01T04:00:00Z| true | **To convert any column to booleans**: 1. Use [`map()`](/flux/v0/stdlib/universe/map/) to iterate over and rewrite rows. 2. Use [`bool()`](/flux/v0/stdlib/universe/bool/) to convert columns values to booleans. ```js data |> map(fn: (r) => ({ r with running: bool(v: r.running) })) ``` ##### Given the following input data: | \_time |running *(int)*| |--------------------|---------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 0 | |2021-01-01T03:00:00Z| 0 | |2021-01-01T04:00:00Z| 1 | ##### The example above returns: | \_time |running *(bool)*| |--------------------|----------------| |2021-01-01T00:00:00Z| true | |2021-01-01T02:00:00Z| false | |2021-01-01T03:00:00Z| false | |2021-01-01T04:00:00Z| true | ## Negate boolean values To negate boolean values, use the [`not` logical operator](/flux/v0/spec/operators/#logical-operators). ``` not true // Returns false not false // Returns true ``` #### Related * [bool() function](/flux/v0/stdlib/universe/bool/) * [toBool() function](/flux/v0/stdlib/universe/tobool/) [basic types](/flux/v0/tags/basic-types/)[data types](/flux/v0/tags/data-types/) | _time | _value (float) | | --- | --- | | _time | _value (float) | | 2021-01-01T00:00:00Z | 1.0 | | 2021-01-01T02:00:00Z | 0.0 | | 2021-01-01T03:00:00Z | 0.0 | | 2021-01-01T04:00:00Z | 1.0 | | _time | _value (bool) | | --- | --- | | _time | _value (bool) | | 2021-01-01T00:00:00Z | true | | 2021-01-01T02:00:00Z | false | | 2021-01-01T03:00:00Z | false | | 2021-01-01T04:00:00Z | true | | _time | running (int) | | --- | --- | | _time | running (int) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 0 | | 2021-01-01T03:00:00Z | 0 | | 2021-01-01T04:00:00Z | 1 | | _time | running (bool) | | --- | --- | | _time | running (bool) | | 2021-01-01T00:00:00Z | true | | 2021-01-01T02:00:00Z | false | | 2021-01-01T03:00:00Z | false | | 2021-01-01T04:00:00Z | true | --- # Work with bytes types Source: https://docs.influxdata.com/flux/v0/data-types/basic/bytes/ A **bytes** type represents a sequence of byte values. **Type name**: `bytes` * [Bytes syntax](#bytes-syntax) * [Convert a column to bytes](#convert-a-column-to-bytes) * [Include the string representation of bytes in a table](#include-the-string-representation-of-bytes-in-a-table) ## Bytes syntax Flux does not provide a bytes literal syntax. Use the [`bytes()` function](/flux/v0/stdlib/universe/bytes/) to convert a**string** into bytes. ``` bytes(v: "hello") // Returns [104 101 108 108 111] ``` > [!Note] > Only string types can be converted to bytes. ## Convert strings to bytes Use `bytes()` or `hex.bytes()` to convert strings to bytes. * [`bytes()`](/flux/v0/stdlib/universe/bytes/): Convert a string to bytes * [`hex.bytes()`](/flux/v0/stdlib/contrib/bonitoo-io/hex/bytes/): Decode hexadecimal value and convert it to bytes. #### Convert a hexadecimal string to bytes ``` import "contrib/bonitoo-io/hex" hex.bytes(v: "FF5733") // Returns [255 87 51] (bytes) ``` ## Include the string representation of bytes in a table Use [`display()`](/flux/v0/stdlib/universe/display/) to return the string representation of bytes and include it as a column value.`display()` represents bytes types as a string of lowercase hexadecimal characters prefixed with `0x`. ```js import "sampledata" sampledata.string() |> map(fn: (r) => ({r with _value: display(v: bytes(v: r._value))})) ``` #### Output |tag| \_time | \_value *(string)* | |---|--------------------|------------------------| |t1 |2021-01-01T00:00:00Z|0x736d706c5f673971637a73| |t1 |2021-01-01T00:00:10Z|0x736d706c5f306d6776396e| |t1 |2021-01-01T00:00:20Z|0x736d706c5f706877363634| |t1 |2021-01-01T00:00:30Z|0x736d706c5f6775767a7934| |t1 |2021-01-01T00:00:40Z|0x736d706c5f357633636365| |t1 |2021-01-01T00:00:50Z|0x736d706c5f7339666d6779| |tag| \_time | \_value *(string)* | |---|--------------------|------------------------| |t2 |2021-01-01T00:00:00Z|0x736d706c5f623565696461| |t2 |2021-01-01T00:00:10Z|0x736d706c5f6575346f7870| |t2 |2021-01-01T00:00:20Z|0x736d706c5f356737747a34| |t2 |2021-01-01T00:00:30Z|0x736d706c5f736f78317574| |t2 |2021-01-01T00:00:40Z|0x736d706c5f77666d373537| |t2 |2021-01-01T00:00:50Z|0x736d706c5f64746e326276| #### Related * [bytes() function](/flux/v0/stdlib/universe/bytes/) * [hex.bytes() function](/flux/v0/stdlib/contrib/bonitoo-io/hex/bytes/) [basic types](/flux/v0/tags/basic-types/)[data types](/flux/v0/tags/data-types/) | tag | _time | _value (string) | | --- | --- | --- | | tag | _time | _value (string) | | t1 | 2021-01-01T00:00:00Z | 0x736d706c5f673971637a73 | | t1 | 2021-01-01T00:00:10Z | 0x736d706c5f306d6776396e | | t1 | 2021-01-01T00:00:20Z | 0x736d706c5f706877363634 | | t1 | 2021-01-01T00:00:30Z | 0x736d706c5f6775767a7934 | | t1 | 2021-01-01T00:00:40Z | 0x736d706c5f357633636365 | | t1 | 2021-01-01T00:00:50Z | 0x736d706c5f7339666d6779 | | tag | _time | _value (string) | | --- | --- | --- | | tag | _time | _value (string) | | t2 | 2021-01-01T00:00:00Z | 0x736d706c5f623565696461 | | t2 | 2021-01-01T00:00:10Z | 0x736d706c5f6575346f7870 | | t2 | 2021-01-01T00:00:20Z | 0x736d706c5f356737747a34 | | t2 | 2021-01-01T00:00:30Z | 0x736d706c5f736f78317574 | | t2 | 2021-01-01T00:00:40Z | 0x736d706c5f77666d373537 | | t2 | 2021-01-01T00:00:50Z | 0x736d706c5f64746e326276 | --- # Work with durations Source: https://docs.influxdata.com/flux/v0/data-types/basic/duration/ A **duration** type represents a length of time with nanosecond precision. **Type name**: `duration` * [Duration syntax](#duration-syntax) * [Convert data types to durations](#convert-data-types-to-durations) * [Operate on durations](#operate-on-durations) ## Duration syntax Duration literals contain integers and unit specifiers. Flux supports the following unit specifiers: * `ns`: nanosecond * `us`: microsecond * `ms`: millisecond * `s`: second * `m`: minute * `h`: hour * `d`: day * `w`: week * `mo`: calendar month * `y`: calendar year ``` 1ns // 1 nanosecond 1us // 1 microsecond 1ms // 1 millisecond 1s // 1 second 1m // 1 minute 1h // 1 hour 1d // 1 day 1w // 1 week 1mo // 1 calendar month 1y // 1 calendar year 3d12h4m25s // 3 days, 12 hours, 4 minutes, and 25 seconds ``` > [!Note] > #### Do not include leading zeros in duration literals > > The integer part of a duration literal should not contain leading zeros. > Leading zeros are parsed as separate integer literals. > For example: > > ``` > 01m // parsed as 0 (integer literal) and 1m (duration literal) > 02h05m // parsed as 0 (integer literal), 2h (duration literal), 0 (integer literal), and 5m (duration literal) > > ``` ## Convert data types to durations Use the [`duration()` function](/flux/v0/stdlib/universe/duration/) to convert the following [basic types](/flux/v0/data-types/basic/) to durations: * **string**: parsed as a duration string and converted to a duration. * **int**: parsed as nanoseconds and converted to a duration. * **uint**: parsed as nanoseconds and converted to a duration. ``` duration(v: "1h30m") // Returns 1h30m duration(v: 1000000) // Returns 1ms duration(v: uint(v: 3000000000)) // Returns 3s ``` > [!Note] > **Flux does not support duration columns.** ## Operate on durations * [Perform arithmetic operations on durations](#perform-arithmetic-operations-on-durations) * [Add a duration to a time value](#add-a-duration-to-a-time-value) * [Subtract a duration from a time value](#subtract-a-duration-from-a-time-value) ### Perform arithmetic operations on durations To perform operations like adding, subtracting, multiplying, or dividing duration values: 1. Use [`int()`](/flux/v0/stdlib/universe/int/) or [`uint()`](/flux/v0/stdlib/universe/uint/)to convert duration values to numeric values. 2. Use [arithmetic operators](/flux/v0/spec/operators/#arithmetic-operators) to operate on numeric values. 3. Use [`duration()`](/flux/v0/stdlib/universe/duration/) to convert the calculated numeric value into a duration. ``` duration(v: int(v: 6h4m) + int(v: 22h32s)) // Returns 1d4h4m32s duration(v: int(v: 22h32s) - int(v: 6h4m)) // Returns 15h56m32s duration(v: int(v: 32m10s) * 10) // Returns 5h21m40s duration(v: int(v: 24h) / 2) // Returns 12h ``` ### Add a duration to a time value 1. Import the [`date` package](/flux/v0/stdlib/date/). 2. Use [`date.add()`](/flux/v0/stdlib/date/add/)to add a duration to a time value. ``` import "date" date.add(d: 1w, to: 2021-01-01T00:00:00Z) // Returns 2021-01-08T00:00:00.000000000Z ``` ### Subtract a duration from a time value 1. Import the [`date` package](/flux/v0/stdlib/date/). 2. Use [`date.sub()`](/flux/v0/stdlib/date/sub/)to subtract a duration from a time value. ``` import "date" date.sub(d: 1w, from: 2021-01-01T00:00:00Z) // Returns 2020-12-25T00:00:00.000000000Z ``` #### Related * [duration() function](/flux/v0/stdlib/universe/duration/) [basic types](/flux/v0/tags/basic-types/)[data types](/flux/v0/tags/data-types/) --- # Work with floats Source: https://docs.influxdata.com/flux/v0/data-types/basic/float/ A **float** type represents a [IEEE-754](https://standards.ieee.org/standard/754-2019.html)64-bit floating-point number. **Type name:** `float` * [Float syntax](#float-syntax) * [Convert data types to floats](#convert-data-types-to-floats) * [Operate on floats](#operate-on-floats) ## Float syntax A float literal contains a decimal integer, a decimal point, and a decimal fraction. ```js 0.0 123.4 -123.456 ``` * [Scientific notation](#scientific-notation) * [Infinity](#infinity) * [Not a Number (NaN)](#not-a-number) ### Scientific notation Flux does not support scientific notation float literal syntax. However, you can use [`float()`](/flux/v0/stdlib/universe/float/) to convert a **scientific notation string** into a float type. ``` 1.23456e+78 // Error: error @1:8-1:9: undefined identifier e float(v: "1.23456e+78") // Returns 1.23456e+78 (float) ``` ### Infinity Flux does not support infinite float literal syntax (`+Inf` and `-Inf`). However, you can use [`float()`](/flux/v0/stdlib/universe/float/) to convert a **infinite string** into a float type. ``` +Inf // Error: error @1:2-1:5: undefined identifier Inf float(v: "+Inf") // Returns +Inf (float) ``` ### Not a Number Flux does not support Not a Number (NaN) float literal syntax. However, you can use [`float()`](/flux/v0/stdlib/universe/float/) to convert a **NaN string** into a float type. ``` NaN // Error: error @1:2-1:5: undefined identifier NaN float(v: "NaN") // Returns NaN (float) ``` ## Convert data types to floats Use the [`float()` function](/flux/v0/stdlib/universe/float/) to convert the following [basic types](/flux/v0/data-types/basic/) to floats: * **string**: must be a numeric string or [scientific notation](#scientific-notation) * **bool**: `true` converts to `1.0`, `false` converts to `0.0` * **int** * **uint** ``` float(v: "1.23") // 1.23 float(v: true) // Returns 1.0 float(v: 123) // Returns 123.0 ``` ### Convert columns to floats Flux lets you iterate over rows in a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)and convert columns to floats. **To convert the `_value` column to floats**, use the [`toFloat()` function](/flux/v0/stdlib/universe/tofloat/). > [!Note] > `toFloat()` only operates on the `_value` column. ```js data |> toFloat() ``` ##### Given the following input data: | \_time |\_value *(int)*| |--------------------|---------------| |2021-01-01T00:00:00Z| 10 | |2021-01-01T02:00:00Z| 20 | |2021-01-01T03:00:00Z| 30 | |2021-01-01T04:00:00Z| 40 | ##### The example above returns: | \_time |\_value *(float)*| |--------------------|-----------------| |2021-01-01T00:00:00Z| 10.0 | |2021-01-01T02:00:00Z| 20.0 | |2021-01-01T03:00:00Z| 30.0 | |2021-01-01T04:00:00Z| 40.0 | **To convert any column to floats**: 1. Use [`map()`](/flux/v0/stdlib/universe/map/) to iterate over and rewrite rows. 2. Use [`float()`](/flux/v0/stdlib/universe/float/) to convert columns values to floats. ```js data |> map(fn: (r) => ({ r with index: float(v: r.index) })) ``` ##### Given the following input data: | \_time |index *(int)*| |--------------------|-------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 2 | |2021-01-01T03:00:00Z| 3 | |2021-01-01T04:00:00Z| 4 | ##### The example above returns: | \_time |index *(float)*| |--------------------|---------------| |2021-01-01T00:00:00Z| 1.0 | |2021-01-01T02:00:00Z| 2.0 | |2021-01-01T03:00:00Z| 3.0 | |2021-01-01T04:00:00Z| 4.0 | ## Operate on floats * [Perform arithmetic operations on floats](#perform-arithmetic-operations-on-floats) * [Compare float values](#compare-float-values) * [Round float values](#round-float-values) * [Flux math package](#flux-math-package) ### Perform arithmetic operations on floats To perform operations like adding, subtracting, multiplying, or dividing float values, use [Flux arithmetic operators](/flux/v0/spec/operators/#arithmetic-operators). Operands must be the same type. ``` 1.23 + 45.67 // Returns 46.9 1.23 - 45.67 // Returns -44.440000000000005 float(v: "12345e+67") * 100.0 // Returns 1.2345000000000001e+73 144.0 / 12.0 // Returns 12.0 10.0 ^ 2.0 // Returns 100.0 ``` > [!Note] > #### Inherent rounding errors in floating-point arithmetic > > To fit an infinite number of real values into a finite number of bits, > computer systems must round floating-point values in arithmetic operations. > This results in small rounding errors in some operations. ### Compare float values Use [Flux comparison operators](/flux/v0/spec/operators/#comparison-operators)to compare float values. Operands must be the same type. The operation returns a float. ``` 12345600.0 == float(v: "1.23456e+07") // Returns true 1.2 > -2.1 // Returns true ``` ### Round float values 1. Import the [`math` package](/flux/v0/stdlib/math/). 2. Use [`math.round()`](/flux/v0/stdlib/math/round/) to round to the nearest whole number. ``` import "math" math.round(x: 1.54) // Returns 2.0 ``` ### Flux math package Use the [`math` package](/flux/v0/stdlib/math/) to perform operations on float values. #### Related * [float() function](/flux/v0/stdlib/universe/float/) * [toFloat() function](/flux/v0/stdlib/universe/tofloat/) [basic types](/flux/v0/tags/basic-types/)[numeric types](/flux/v0/tags/numeric-types/)[data types](/flux/v0/tags/data-types/) | _time | _value (int) | | --- | --- | | _time | _value (int) | | 2021-01-01T00:00:00Z | 10 | | 2021-01-01T02:00:00Z | 20 | | 2021-01-01T03:00:00Z | 30 | | 2021-01-01T04:00:00Z | 40 | | _time | _value (float) | | --- | --- | | _time | _value (float) | | 2021-01-01T00:00:00Z | 10.0 | | 2021-01-01T02:00:00Z | 20.0 | | 2021-01-01T03:00:00Z | 30.0 | | 2021-01-01T04:00:00Z | 40.0 | | _time | index (int) | | --- | --- | | _time | index (int) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 2 | | 2021-01-01T03:00:00Z | 3 | | 2021-01-01T04:00:00Z | 4 | | _time | index (float) | | --- | --- | | _time | index (float) | | 2021-01-01T00:00:00Z | 1.0 | | 2021-01-01T02:00:00Z | 2.0 | | 2021-01-01T03:00:00Z | 3.0 | | 2021-01-01T04:00:00Z | 4.0 | --- # Work with integers Source: https://docs.influxdata.com/flux/v0/data-types/basic/int/ An **integer** type represents a signed 64-bit integer. **Type name**: `int` **Min value**: `-9223372036854775808` **Max value**: `9223372036854775807` * [Integer syntax](#integer-syntax) * [Convert data types to integers](#convert-data-types-to-integers) * [Operate on integers](#operate-on-integers) ## Integer syntax An integer literal contains one or more digits (0-9) optionally preceded by`-` to indicate a negative number.`-0` is equivalent to `0` and is not a negative number. ```js 0 2 1254 -1254 ``` ## Convert data types to integers Use the [`int()` function](/flux/v0/stdlib/universe/int/) to convert the following [basic types](/flux/v0/data-types/basic/) to integers: * **string**: returns the integer equivalent of the numeric string (`[0-9]`) * **bool**: returns `1` for `true` or `0` for `false` * **duration**: returns the number of nanoseconds in the duration * **time**: returns the equivalent [nanosecond epoch timestamp](/influxdb/cloud/reference/glossary/#unix-timestamp) * **float**: truncates the float value at the decimal * **uint**: returns the integer equivalent of the unsigned integer ``` int(v: "123") // 123 int(v: true) // Returns 1 int(v: 1d3h24m) // Returns 98640000000000 int(v: 2021-01-01T00:00:00Z) // Returns 1609459200000000000 int(v: 12.54) // Returns 12 ``` > [!Note] > #### Round float values before converting to integers > > When converting [floats](/flux/v0/data-types/basic/float/) to integers,`int()` *truncates* the float value at the decimal (for example `12.54` to `12`). > You may want to round float values to the nearest whole number (`12.54` to `13`) before converting. > To do this: > > 1. Import the [`math` package](/flux/v0/stdlib/math/). > 2. Use [`math.round()`](/flux/v0/stdlib/math/round/) to round the float value > before converting it to an integer. > > ``` > import "math" > > int(v: math.round(x: 12.54)) > // Returns 13 > > ``` ### Convert a hexadecimal string to an integer To convert a hexadecimal string representation of a number to an integer: 1. Import the [`contrib/bonitoo-io/hex` package](/flux/v0/stdlib/contrib/bonitoo-io/hex/). 2. Use [`hex.int()`](/flux/v0/stdlib/contrib/bonitoo-io/hex/int/) to convert the hexadecimal string to an integer. ``` import "contrib/bonitoo-io/hex" hex.int(v: "1e240") // Returns 123456 ``` ### Convert columns to integers Flux lets you iterate over rows in a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)and convert columns to integers. **To convert the `_value` column to integers**, use the [`toInt()` function](/flux/v0/stdlib/universe/toint/). > [!Note] > `toInt()` only operates on the `_value` column. ```js data |> toInt() ``` ##### Given the following input data: | \_time |\_value *(float)*| |--------------------|-----------------| |2021-01-01T00:00:00Z| 1.23 | |2021-01-01T02:00:00Z| 4.56 | |2021-01-01T03:00:00Z| 7.89 | |2021-01-01T04:00:00Z| 10.11 | ##### The example above returns: | \_time |\_value *(int)*| |--------------------|---------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 4 | |2021-01-01T03:00:00Z| 7 | |2021-01-01T04:00:00Z| 10 | **To convert any column to integers**: 1. Use [`map()`](/flux/v0/stdlib/universe/map/) to iterate over and rewrite rows. 2. Use [`int()`](/flux/v0/stdlib/universe/int/) to convert columns values to integers. ```js data |> map(fn: (r) => ({ r with uid: int(v: r.uid) })) ``` ##### Given the following input data: | \_time |index *(string)*| |--------------------|----------------| |2021-01-01T00:00:00Z| 100010024 | |2021-01-01T02:00:00Z| 100050213 | |2021-01-01T03:00:00Z| 200130763 | |2021-01-01T04:00:00Z| 101420099 | ##### The example above returns: | \_time |index *(int)*| |--------------------|-------------| |2021-01-01T00:00:00Z| 100010024 | |2021-01-01T02:00:00Z| 100050213 | |2021-01-01T03:00:00Z| 200130763 | |2021-01-01T04:00:00Z| 101420099 | ## Operate on integers * [Perform arithmetic operations on integers](#perform-arithmetic-operations-on-integers) * [Perform bitwise operations on integers](#perform-bitwise-operations-on-integers) * [Compare integers](#compare-integers) ### Perform arithmetic operations on integers To perform operations like adding, subtracting, multiplying, or dividing integers, use [Flux arithmetic operators](/flux/v0/spec/operators/#arithmetic-operators). Operands must be the same type. The operation returns an integer. > [!Note] > When operating with integer operands, fractional results are truncated at the decimal. ``` 1 + 45 // Returns 46 1 - 45 // Returns -44 12 * 100 // Returns 1200 100 / 200 // Returns 0 10 ^ 2 // Returns 100 ``` ### Perform bitwise operations on integers Use the [`experimental/bitwise` package](/flux/v0/stdlib/experimental/bitwise/)to perform bitwise operations on integers. ``` import "experimental/bitwise" bitwise.sand(a: 12, b: 21) // Returns 4 bitwise.sor(a: 12, b: 21) // Returns 29 bitwise.sxor(a: 12, b: 21) // Returns 25 bitwise.sclear(a: 12, b: 21) // Returns 8 bitwise.snot(a: 12) // Returns -13 bitwise.slshift(a: 12, b: 21) // Returns 25165824 bitwise.srshift(a: 21, b: 4) // Returns 1 ``` ### Compare integers Use [Flux comparison operators](/flux/v0/spec/operators/#comparison-operators)to compare integers. Operands must be the same type. The operation returns a boolean. ``` 12345600 == 12345601 // Returns false 2 > -2 // Returns true ``` #### Related * [int() function](/flux/v0/stdlib/universe/int/) * [toInt() function](/flux/v0/stdlib/universe/toint/) * [hex.int() function](/flux/v0/stdlib/contrib/bonitoo-io/hex/int/) * [bitwise package](/flux/v0/stdlib/experimental/bitwise/) [basic types](/flux/v0/tags/basic-types/)[numeric types](/flux/v0/tags/numeric-types/)[data types](/flux/v0/tags/data-types/) | _time | _value (float) | | --- | --- | | _time | _value (float) | | 2021-01-01T00:00:00Z | 1.23 | | 2021-01-01T02:00:00Z | 4.56 | | 2021-01-01T03:00:00Z | 7.89 | | 2021-01-01T04:00:00Z | 10.11 | | _time | _value (int) | | --- | --- | | _time | _value (int) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 4 | | 2021-01-01T03:00:00Z | 7 | | 2021-01-01T04:00:00Z | 10 | | _time | index (string) | | --- | --- | | _time | index (string) | | 2021-01-01T00:00:00Z | 100010024 | | 2021-01-01T02:00:00Z | 100050213 | | 2021-01-01T03:00:00Z | 200130763 | | 2021-01-01T04:00:00Z | 101420099 | | _time | index (int) | | --- | --- | | _time | index (int) | | 2021-01-01T00:00:00Z | 100010024 | | 2021-01-01T02:00:00Z | 100050213 | | 2021-01-01T03:00:00Z | 200130763 | | 2021-01-01T04:00:00Z | 101420099 | --- # Work with null types Source: https://docs.influxdata.com/flux/v0/data-types/basic/null/ The **null type** represents a missing or unknown value. **Type name**: `null` * [Null syntax](#null-syntax) * [Check if a column value is null](#check-if-a-column-value-is-null) * [Include null values in an ad hoc stream of tables](#include-null-values-in-an-ad-hoc-stream-of-tables) ## Null syntax Null types exist in [columns](/flux/v0/get-started/data-model/#column) of other [basic types](/flux/v0/data-types/basic/). Flux does not provide a literal syntax for a *null* value, however, you can use[`debug.null()`](/flux/v0/stdlib/internal/debug/null/) to return a null value of a specified type. ```js import "internal/debug" // Return a null string debug.null(type: "string") // Return a null integer debug.null(type: "int") // Return a null boolean debug.null(type: "bool") ``` > [!Note] > An empty string (`""`) **is not** a *null* value. ## Check if a column value is null In functions that iterate over rows (such as [`filter()`](/flux/v0/stdlib/universe/filter/)or [`map()`](/flux/v0/stdlib/universe/map/)), use the[`exists` logical operator](/flux/v0/spec/operators/#logical-operators) to check if a column value is *null*. ##### Filter out rows with null values ```js data |> filter(fn: (r) => exists r._value) ``` ##### Given the following input data: | \_time |\_value| |--------------------|-------| |2021-01-01T00:00:00Z| 1.2 | |2021-01-01T02:00:00Z| | |2021-01-01T03:00:00Z| 2.5 | |2021-01-01T04:00:00Z| | ##### The example above returns: | \_time |\_value| |--------------------|-------| |2021-01-01T00:00:00Z| 1.2 | |2021-01-01T03:00:00Z| 2.5 | ## Include null values in an ad hoc stream of tables 1. Use [`array.from()`](/flux/v0/stdlib/array/from/) to create an ad hoc stream of tables. 2. Use [`debug.null()`](/flux/v0/stdlib/internal/debug/null/) to include null column values. ```js import "array" import "internal/debug" array.from( rows: [ {a: 1, b: 2, c: 3, d: "four"}, {a: debug.null(type: "int"), b: 5, c: 6, d: debug.null(type: "string")} ] ) ``` ##### The example above returns: | a | b | c | d | |---|---|---|----| | 1 | 2 | 3 |four| | | 5 | 6 | | #### Related * [debug.null() function](/flux/v0/stdlib/internal/debug/null/) [basic types](/flux/v0/tags/basic-types/)[data types](/flux/v0/tags/data-types/) | _time | _value | | --- | --- | | _time | _value | | 2021-01-01T00:00:00Z | 1.2 | | 2021-01-01T02:00:00Z | | | 2021-01-01T03:00:00Z | 2.5 | | 2021-01-01T04:00:00Z | | | _time | _value | | --- | --- | | _time | _value | | 2021-01-01T00:00:00Z | 1.2 | | 2021-01-01T03:00:00Z | 2.5 | | a | b | c | d | | --- | --- | --- | --- | | a | b | c | d | | 1 | 2 | 3 | four | | | 5 | 6 | | --- # Work with regular expression types Source: https://docs.influxdata.com/flux/v0/data-types/basic/regexp/ A **regular expression** type represents a regular expression pattern. **Type name**: `regexp` * [Regular expression syntax](#regular-expression-syntax) * [Use regular expression flags](#use-regular-expression-flags) * [Use regular expressions in predicate expressions](#use-regular-expressions-in-predicate-expressions) * [Convert a string to a regular expression](#convert-a-string-to-a-regular-expression) * [Examples](#examples) ## Regular expression syntax Flux uses the [Go regexp implementation and syntax](https://pkg.go.dev/regexp). This syntax is similar to regular expressions in Perl, Python, and other languages. Regular expression literals are enclosed in forward slash characters (`/`). ```js /^[a-z0-9]+$/ ``` ## Use regular expression flags Flux supports the following regular expression flags: |Flag| Description | |----|-------------------------------------------------------------------------------| | i | case-insensitive | | m |multi-line mode: `^` and `$` match begin/end line in addition to begin/end text| | s | let `.` match `\n` | | U | ungreedy: swap meaning of `x*` and `x*?`, `x+` and `x+?`, etc | Include regular expression flags at the beginning of your regular expression pattern enclosed in parentheses (`()`) and preceded by a question mark (`?`). ```js /(?iU)foo*/ ``` ## Use regular expressions in predicate expressions To use regular expressions in [predicate expressions](/flux/v0/get-started/syntax-basics/#predicate-expressions), use the [`=~` and `!~` comparison operators](/flux/v0/spec/operators/#comparison-operators). The left operand must be a string. The right operand must be a regular expression. ``` "abc" =~ /\w/ // Returns true "z09se89" =~ /^[a-z0-9]{7}$/ // Returns true "foo" !~ /^f/ // Returns false "FOO" =~ /(?i)foo/ // Returns true ``` ## Convert a string to a regular expression 1. Import the [`regexp` package](/flux/v0/stdlib/regexp/). 2. Use [`regexp.compile()`](/flux/v0/stdlib/regexp/compile) to compile a string into a regular expression type. ``` import "regexp" regexp.compile(v: "^- [a-z0-9]{7}") // Returns ^- [a-z0-9]{7} (regexp type) ``` ## Examples * [Replace all substrings that match a regular expression](#replace-all-substrings-that-match-a-regular-expression) * [Return the first regular expression match in a string](#return-the-first-regular-expression-match-in-a-string) * [Escape regular expression metacharacters in a string](#escape-regular-expression-metacharacters-in-a-string) ### Replace all substrings that match a regular expression 1. Import the [`regexp` package](/flux/v0/stdlib/regexp). 2. Use [`regexp.replaceAllString()`](/flux/v0/stdlib/regexp/replaceallstring/)and provide the following parameters: * **r**: regular expression * **v**: string to search * **t**: replacement for matches to **r**. ``` import "regexp" regexp.replaceAllString(r: /a(x*)b/, v: "-ab-axxb-", t: "T") // Returns "-T-T-" ``` ### Return the first regular expression match in a string 1. Import the [`regexp` package](/flux/v0/stdlib/regexp). 2. Use [`regexp.findString()`](/flux/v0/stdlib/regexp/findstring/) to return the first regular expression match in a string. Provide the following parameters: * **r**: regular expression * **v**: string to search ``` import "regexp" regexp.findString(r: /foo.?/, v: "seafood fool") // Returns "food" ``` ### Escape regular expression metacharacters in a string If a string contains regular expression metacharacters that should be evaluated as literal characters, escape the metacharacters before converting the string to a regular expression: 1. Import the [`regexp` package](/flux/v0/stdlib/regexp). 2. Use [`regexp.quoteMeta()`](/flux/v0/stdlib/regexp/quotemeta/)and provide the string to escape regular expression metacharacters in: ``` import "regexp" regexp.quoteMeta(v: ".+*?()|[]{}^$") // Returns "\.\+\*\?\(\)\|\[\]\{\}\^\$" ``` #### Related * [regexp package](/flux/v0/stdlib/regexp/) [regexp types](/flux/v0/tags/regexp-types/)[data types](/flux/v0/tags/data-types/) | Flag | Description | | --- | --- | | Flag | Description | | i | case-insensitive | | m | multi-line mode: ^ and $ match begin/end line in addition to begin/end text | | s | let . match \n | | U | ungreedy: swap meaning of x* and x*? , x+ and x+? , etc | --- # Work with strings Source: https://docs.influxdata.com/flux/v0/data-types/basic/string/ A **string** type represents a sequence of characters. Strings are immutable and cannot be modified once created. **Type name**: `string` * [String syntax](#string-syntax) * [Convert data types to strings](#convert-data-types-to-strings) * [Operate on strings](#operate-on-strings) * [Interpolate strings](#interpolate-strings) * [Concatenate strings](#concatenate-strings) ## String syntax A **string** literal is represented by a sequence of characters enclosed in double quotes (`"`). Any character may appear inside a string literal except an unescaped double quote. String literals support several [escape sequences](/flux/v0/spec/lexical-elements/#string-literals)and [hex encoding using `\x` as a prefix](/flux/v0/spec/lexical-elements/#string-literals). ```js "abc" "string with double \" quote" "string with backslash \\" "日本語" "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" ``` ## Convert data types to strings Use the [`string()` function](/flux/v0/stdlib/universe/string/) to convert other [basic types](/flux/v0/data-types/basic/) to strings: * boolean * bytes * duration * float * int * uint * time ``` string(v: 42) // Returns "42" ``` ### Convert regular expressions to strings To convert a [regular expression](/flux/v0/data-types/basic/regexp/) to a string: 1. Import the [`regexp` package](/flux/v0/stdlib/regexp/). 2. Use [`regexp.getString()`](/flux/v0/stdlib/regexp/getstring/) and provide the regular expression to convert to a string. ``` import "regexp" regexp.getString(r: /[a-zA-Z]/) // Returns [a-zA-Z] (string) ``` ### Convert data types to hexadecimal strings To convert [basic types](/flux/v0/data-types/basic/) to hexadecimal strings: 1. Import the [`contrib/bonitoo-io/hex` package](/flux/v0/stdlib/contrib/bonitoo-io/hex/). 2. Use [`hex.string()`](/flux/v0/stdlib/contrib/bonitoo-io/hex/string/) to convert other a value to a hexadecimal string. ``` import "contrib/bonitoo-io/hex" hex.string(v: 123456) // Returns 1e240 ``` ### Convert columns to strings Flux lets you iterate over rows in a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)and convert columns to strings. **To convert the `_value` column to strings**, use the [`toString()` function](/flux/v0/stdlib/universe/tostring/). > [!Note] > `toString()` only operates on the `_value` column. ```js data |> toString() ``` ##### Given the following input data: | \_time |\_value *(int)*| |--------------------|---------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 2 | |2021-01-01T03:00:00Z| 3 | |2021-01-01T04:00:00Z| 4 | ##### The example above returns: | \_time |\_value *(string)*| |--------------------|------------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 2 | |2021-01-01T03:00:00Z| 3 | |2021-01-01T04:00:00Z| 4 | **To convert any column to strings**: 1. Use [`map()`](/flux/v0/stdlib/universe/map/) to iterate over and rewrite rows. 2. Use [`string()`](/flux/v0/stdlib/universe/string/) to convert columns values to strings. ```js data |> map(fn: (r) => ({ r with level: string(v: r.level) })) ``` ##### Given the following input data: | \_time |level *(int)*| |--------------------|-------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 2 | |2021-01-01T03:00:00Z| 3 | |2021-01-01T04:00:00Z| 4 | ##### The example above returns: | \_time |level *(string)*| |--------------------|----------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 2 | |2021-01-01T03:00:00Z| 3 | |2021-01-01T04:00:00Z| 4 | ## Operate on strings Use functions in the [Flux strings package](/flux/v0/stdlib/strings/) to perform operations including: * [Compare two strings](/flux/v0/stdlib/strings/compare/) * [Replace substrings in a string](/flux/v0/stdlib/strings/replace/) * [Return the length of a string](/flux/v0/stdlib/strings/strlen/) * [Split a string into an array](/flux/v0/stdlib/strings/split/) * [Join an array into a string](/flux/v0/stdlib/strings/joinstr/) * [and more](/flux/v0/stdlib/strings/) ## Interpolate strings To interpolate strings in another Flux string, enclose embedded [expressions](/flux/v0/spec/expressions/)in a dollar sign and curly braces `${}`. Flux replaces the placeholder with the result of the embedded expression and returns a string literal. ``` name = "John" "My name is ${name}." // My name is John. d = 1m "the answer is ${d}" // the answer is 1m t0 = 2016-06-13T17:43:50Z "the answer is ${t0}" // the answer is 2016-06-13T17:43:50.000000000Z p = {name: "John", age: 42} "My name is ${p.name} and I'm ${p.age} years old." // My name is John and I'm 42 years old. ``` *String interpolation expressions must satisfy the[Stringable constraint](/flux/v0/spec/types/#stringable-constraint).* ## Concatenate strings To concatenate Flux strings, use the `+` operator between string values or[expressions](/flux/v0/spec/expressions/) that resolve to strings. Flux resolves expressions and returns a single concatenated string. > [!Note] > Concatenated expressions must resolve to strings. ``` name = "John" "My name is " + name + "." // My name is John. d = 1m "the answer is " + string(v: d) // the answer is 1m t0 = 2016-06-13T17:43:50Z "the answer is " + string(v: t0) // the answer is 2016-06-13T17:43:50.000000000Z p = {name: "John", age: 42} "My name is " + p.name + " and I'm " + string(v: p.age) + " years old." // My name is John and I'm 42 years old. ``` #### Related * [string() function](/flux/v0/stdlib/universe/string/) * [toString() function](/flux/v0/stdlib/universe/tostring/) * [strings package](/flux/v0/stdlib/strings/) [basic types](/flux/v0/tags/basic-types/)[data types](/flux/v0/tags/data-types/) | _time | _value (int) | | --- | --- | | _time | _value (int) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 2 | | 2021-01-01T03:00:00Z | 3 | | 2021-01-01T04:00:00Z | 4 | | _time | _value (string) | | --- | --- | | _time | _value (string) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 2 | | 2021-01-01T03:00:00Z | 3 | | 2021-01-01T04:00:00Z | 4 | | _time | level (int) | | --- | --- | | _time | level (int) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 2 | | 2021-01-01T03:00:00Z | 3 | | 2021-01-01T04:00:00Z | 4 | | _time | level (string) | | --- | --- | | _time | level (string) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 2 | | 2021-01-01T03:00:00Z | 3 | | 2021-01-01T04:00:00Z | 4 | --- # Work with time types Source: https://docs.influxdata.com/flux/v0/data-types/basic/time/ A **time** type represents a single point in time with nanosecond precision. **Type name**: `time` * [Time syntax](#time-syntax) * [Convert data types to time](#convert-data-types-to-time) * [Operate on time](#operate-on-time) ## Time syntax Time literals are represented by [RFC3339 timestamps](/influxdb/cloud/reference/glossary/#rfc3339-timestamp). ``` YYYY-MM-DD YYYY-MM-DDT00:00:00Z YYYY-MM-DDT00:00:00.000Z ``` ## Convert data types to time Use the [`time()` function](/flux/v0/stdlib/universe/time/) to convert the following [basic types](/flux/v0/data-types/basic/) to time: * **string**: parsed as an [RFC3339 timestamp](/influxdb/cloud/reference/glossary/#rfc3339-timestamp)and converted to a time value. * **int**: parsed as a [Unix nanosecond timestamp](/influxdb/cloud/reference/glossary/#unix-timestamp)and converted to a time value. * **uint**: parsed as a [Unix nanosecond timestamp](/influxdb/cloud/reference/glossary/#unix-timestamp)and converted to a time value. ``` time(v: "2021-01-01") // Returns 2021-01-01T00:00:00.000000000Z time(v: 1609459200000000000) // Returns 2021-01-01T00:00:00.000000000Z time(v: uint(v: 1609459200000000000)) // Returns 2021-01-01T00:00:00.000000000Z ``` ### Convert columns to time Flux lets you iterate over rows in a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)and convert columns to time. **To convert the `_value` column to time**, use the [`toTime()` function](/flux/v0/stdlib/universe/totime/). > [!Note] > `toTime()` only operates on the `_value` column. ```js data |> toTime() ``` ##### Given the following input data: | \_time |\_value *(int)*| |--------------------|---------------| |2021-01-01T00:00:00Z| 10000000000 | |2021-01-01T02:00:00Z| 20000000000 | |2021-01-01T03:00:00Z| 30000000000 | |2021-01-01T04:00:00Z| 40000000000 | ##### The example above returns: | \_time | \_value *(time)* | |--------------------|--------------------| |2021-01-01T00:00:00Z|1970-01-01T00:00:10Z| |2021-01-01T02:00:00Z|1970-01-01T00:00:20Z| |2021-01-01T03:00:00Z|1970-01-01T00:00:30Z| |2021-01-01T04:00:00Z|1970-01-01T00:00:40Z| **To convert any column to time**: 1. Use [`map()`](/flux/v0/stdlib/universe/map/) to iterate over and rewrite rows. 2. Use [`time()`](/flux/v0/stdlib/universe/time/) to convert columns values to time. ```js data |> map(fn: (r) => ({ r with epoch_ns: time(v: r.epoch_ns) })) ``` ##### Given the following input data: | \_time |epoch\_ns *(int)*| |--------------------|-----------------| |2021-01-01T00:00:00Z| 10000000000 | |2021-01-01T02:00:00Z| 20000000000 | |2021-01-01T03:00:00Z| 30000000000 | |2021-01-01T04:00:00Z| 40000000000 | ##### The example above returns: | \_time | epoch\_ns *(time)* | |--------------------|--------------------| |2021-01-01T00:00:00Z|1970-01-01T00:00:10Z| |2021-01-01T02:00:00Z|1970-01-01T00:00:20Z| |2021-01-01T03:00:00Z|1970-01-01T00:00:30Z| |2021-01-01T04:00:00Z|1970-01-01T00:00:40Z| ## Operate on time * [Truncate timestamps to a specified unit](#truncate-timestamps-to-a-specified-unit) * [Parse units of time from a timestamp](#parse-units-of-time-from-a-timestamp) * [Add a duration to a time value](#add-a-duration-to-a-time-value) * [Subtract a duration from a time value](#subtract-a-duration-from-a-time-value) ### Truncate timestamps to a specified unit Truncating timestamps can be helpful when normalizing irregular timestamps. To truncate timestamps to a specified unit: 1. Import the [`date` package](/flux/v0/stdlib/date/). 2. Use [`date.truncate()`](/flux/v0/stdlib/date/truncate/), and provide the unit of time to truncate to. > [!Note] > #### Truncate to weeks > > When truncating a time value to the week (`1w`), weeks are determined using the**Unix epoch (1970-01-01T00:00:00Z UTC)**. The Unix epoch was on a Thursday, so > all calculated weeks begin on Thursday. ``` t0 = 2021-01-08T14:54:10.023849Z date.truncate(t: t0, unit: 1ms) // Returns 2021-01-08T14:54:10.023000000Z date.truncate(t: t0, unit: 1m) // Returns 2021-01-08T14:54:00.000000000Z date.truncate(t: t0, unit: 1w) // Returns 2021-01-07T00:00:00.000000000Z date.truncate(t: t0, unit: 1mo) // Returns 2021-01-01T00:00:00.000000000Z ``` **To truncate the `_time` column, use [`truncateTimeColumn()`](/flux/v0/stdlib/universe/truncatetimecolumn/)**: ```js data |> truncateTimeColumn(unit: 1m) ``` ##### Given the following input data: | \_time |\_value| |--------------------|-------| |2021-01-01T00:00:33Z| 1.0 | |2021-01-01T00:01:10Z| 1.1 | |2021-01-01T00:02:45Z| 3.6 | |2021-01-01T00:03:23Z| 2.5 | ##### The example above returns: | \_time |\_value| |--------------------|-------| |2021-01-01T00:00:00Z| 1.0 | |2021-01-01T00:01:00Z| 1.1 | |2021-01-01T00:02:00Z| 3.6 | |2021-01-01T00:03:00Z| 2.5 | ### Parse units of time from a timestamp To parse a specific unit of time from a time value: 1. Import the [`date` package](/flux/v0/stdlib/date/). 2. Use functions in the `date` package to return specific units of time from a timestamp. ``` import "date" t0 = 2021-01-08T14:54:10.023849Z date.minute(t: t0) // Returns 54 date.year(t: t0) // Returns 2021 date.quarter(t: t0) // Returns 1 ``` ### Add a duration to a time value To add a [duration](/flux/v0/data-types/basic/duration/) to a time value: 1. Import the [`date` package](/flux/v0/stdlib/date/). 2. Use [`date.add()`](/flux/v0/stdlib/date/add/)to add a duration to a time value. ``` import "date" date.add(d: 1w, to: 2021-01-01T00:00:00Z) // Returns 2021-01-08T00:00:00.000000000Z ``` ### Subtract a duration from a time value To subtract a [duration](/flux/v0/data-types/basic/duration/) from a time value: 1. Import the [`date` package](/flux/v0/stdlib/date/). 2. Use [`date.sub()`](/flux/v0/stdlib/date/sub/)to subtract a duration from a time value. ``` import "date" date.sub(d: 1w, from: 2021-01-01T00:00:00Z) // Returns 2020-12-25T00:00:00.000000000Z ``` #### Related * [time() function](/flux/v0/stdlib/universe/time/) * [toTime() function](/flux/v0/stdlib/universe/totime/) [basic types](/flux/v0/tags/basic-types/)[data types](/flux/v0/tags/data-types/)[date/time](/flux/v0/tags/date/time/) | _time | _value (int) | | --- | --- | | _time | _value (int) | | 2021-01-01T00:00:00Z | 10000000000 | | 2021-01-01T02:00:00Z | 20000000000 | | 2021-01-01T03:00:00Z | 30000000000 | | 2021-01-01T04:00:00Z | 40000000000 | | _time | _value (time) | | --- | --- | | _time | _value (time) | | 2021-01-01T00:00:00Z | 1970-01-01T00:00:10Z | | 2021-01-01T02:00:00Z | 1970-01-01T00:00:20Z | | 2021-01-01T03:00:00Z | 1970-01-01T00:00:30Z | | 2021-01-01T04:00:00Z | 1970-01-01T00:00:40Z | | _time | epoch_ns (int) | | --- | --- | | _time | epoch_ns (int) | | 2021-01-01T00:00:00Z | 10000000000 | | 2021-01-01T02:00:00Z | 20000000000 | | 2021-01-01T03:00:00Z | 30000000000 | | 2021-01-01T04:00:00Z | 40000000000 | | _time | epoch_ns (time) | | --- | --- | | _time | epoch_ns (time) | | 2021-01-01T00:00:00Z | 1970-01-01T00:00:10Z | | 2021-01-01T02:00:00Z | 1970-01-01T00:00:20Z | | 2021-01-01T03:00:00Z | 1970-01-01T00:00:30Z | | 2021-01-01T04:00:00Z | 1970-01-01T00:00:40Z | | _time | _value | | --- | --- | | _time | _value | | 2021-01-01T00:00:33Z | 1.0 | | 2021-01-01T00:01:10Z | 1.1 | | 2021-01-01T00:02:45Z | 3.6 | | 2021-01-01T00:03:23Z | 2.5 | | _time | _value | | --- | --- | | _time | _value | | 2021-01-01T00:00:00Z | 1.0 | | 2021-01-01T00:01:00Z | 1.1 | | 2021-01-01T00:02:00Z | 3.6 | | 2021-01-01T00:03:00Z | 2.5 | --- # Work with unsigned integers Source: https://docs.influxdata.com/flux/v0/data-types/basic/uint/ An **unsigned integer** (uinteger) type represents a unsigned 64-bit integer. **Type name**: `uint` **Min value**: `0` **Max value**: `18446744073709551615` * [UInteger syntax](#uinteger-syntax) * [Convert data types to uintegers](#convert-data-types-to-uintegers) * [Operate on uintegers](#operate-on-uintegers) ## UInteger syntax Flux does not provide a uinteger literal syntax. However, you can use [`uint()`](/flux/v0/stdlib/universe/uint/) to [convert basic data types into a uinteger](#convert-data-types-to-uintegers). ``` uint(v: 123) // Returns 123 (uint) ``` ## Convert data types to uintegers Use the [`uint()` function](/flux/v0/stdlib/universe/uint/) to convert the following [basic types](/flux/v0/data-types/basic/) to uintegers: * **string**: returns the uinteger equivalent of the numeric string (`[0-9]`) * **bool**: returns `1` for `true` or `0` for `false` * **duration**: returns the number of nanoseconds in the duration * **time**: returns the equivalent [nanosecond epoch timestamp](/influxdb/cloud/reference/glossary/#unix-timestamp) * **float**: truncates the float value at the decimal and returns the uinteger equivalent * **int**: returns the uinteger equivalent of the integer ``` uint(v: "123") // 123 uint(v: true) // Returns 1 uint(v: 1d3h24m) // Returns 98640000000000 uint(v: 2021-01-01T00:00:00Z) // Returns 1609459200000000000 uint(v: 12.54) // Returns 12 uint(v: -54321) // Returns 18446744073709497295 ``` > [!Note] > #### Round float values before converting to uintegers > > When converting [floats](/flux/v0/data-types/basic/float/) to integers,`uint()` *truncates* the float value at the decimal (for example `12.54` to `12`). > You may want to round float values to the nearest whole number (`12.54` to `13`) before converting. > To do this: > > 1. Import the [`math` package](/flux/v0/stdlib/math/). > 2. Use [`math.round()`](/flux/v0/stdlib/math/round/) to round the float value > before converting it to a uinteger. > > ``` > import "math" > > uint(v: math.round(x: 12.54)) > // Returns 13 > > ``` ### Convert a hexadecimal string to a uinteger To convert a hexadecimal string representation of a number to a uinteger: 1. Import the [`contrib/bonitoo-io/hex` package](/flux/v0/stdlib/contrib/bonitoo-io/hex/). 2. Use [`hex.uint()`](/flux/v0/stdlib/contrib/bonitoo-io/hex/uint/) to convert the hexadecimal string to a uinteger. ``` import "contrib/bonitoo-io/hex" hex.uint(v: "-1e240") // Returns 123456 ``` ### Convert columns to uintegers Flux lets you iterate over rows in a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)and convert columns to uintegers. **To convert the `_value` column to uintegers**, use the [`toUInt()` function](/flux/v0/stdlib/universe/touint/). > [!Note] > `toUInt()` only operates on the `_value` column. ```js data |> toUInt() ``` ##### Given the following input data: | \_time |\_value *(float)*| |--------------------|-----------------| |2021-01-01T00:00:00Z| 1.23 | |2021-01-01T02:00:00Z| 4.56 | |2021-01-01T03:00:00Z| \-7.89 | |2021-01-01T04:00:00Z| 10.11 | ##### The example above returns: | \_time | \_value *(uint)* | |--------------------|--------------------| |2021-01-01T00:00:00Z| 1 | |2021-01-01T02:00:00Z| 4 | |2021-01-01T03:00:00Z|18446744073709551609| |2021-01-01T04:00:00Z| 10 | **To convert any column to uintegers**: 1. Use [`map()`](/flux/v0/stdlib/universe/map/) to iterate over and rewrite rows. 2. Use [`uint()`](/flux/v0/stdlib/universe/uint/) to convert columns values to uintegers. ```js data |> map(fn: (r) => ({ r with uid: uint(v: r.uid) })) ``` ##### Given the following input data: | \_time |index *(string)*| |--------------------|----------------| |2021-01-01T00:00:00Z| 100010024 | |2021-01-01T02:00:00Z| 100050213 | |2021-01-01T03:00:00Z| 200130763 | |2021-01-01T04:00:00Z| 101420099 | ##### The example above returns: | \_time |index *(uint)*| |--------------------|--------------| |2021-01-01T00:00:00Z| 100010024 | |2021-01-01T02:00:00Z| 100050213 | |2021-01-01T03:00:00Z| 200130763 | |2021-01-01T04:00:00Z| 101420099 | ## Operate on uintegers * [Perform arithmetic operations on uintegers](#perform-arithmetic-operations-on-uintegers) * [Perform bitwise operations on uintegers](#perform-bitwise-operations-on-uintegers) * [Compare uintegers](#compare-uintegers) ### Perform arithmetic operations on uintegers To perform operations like adding, subtracting, multiplying, or dividing uintegers, use [Flux arithmetic operators](/flux/v0/spec/operators/#arithmetic-operators). Operands must be the same type. The operation returns an uinteger. > [!Note] > When operating with uinteger operands, fractional results are truncated at the decimal. ``` uint(v: 1) + uint(v: 45) // Returns 46 uint(v: 1) - uint(v: 45) // Returns 18446744073709551572 uint(v: 12) * uint(v: 100) // Returns 1200 uint(v: 100) / uint(v: 200) // Returns 0 uint(v: 10) ^ uint(v: 2) // Returns 100 ``` ### Perform bitwise operations on uintegers Use the [`experimental/bitwise` package](/flux/v0/stdlib/experimental/bitwise/)to perform bitwise operations on uintegers. ``` import "experimental/bitwise" bitwise.uand(a: uint(v: 12), b: uint(v: 21)) // Returns 4 bitwise.uor(a: uint(v: 12), b: uint(v: 21)) // Returns 29 bitwise.uxor(a: uint(v: 12), b: uint(v: 21)) // Returns 25 bitwise.uclear(a: uint(v: 12), b: uint(v: 21)) // Returns 8 bitwise.unot(a: uint(v: 12)) // Returns 18446744073709551603 bitwise.ulshift(a: uint(v: 12), b: uint(v: 21)) // Returns 25165824 bitwise.urshift(a: uint(v: 21), b: uint(v: 4)) // Returns 1 ``` ### Compare uintegers Use [Flux comparison operators](/flux/v0/spec/operators/#comparison-operators)to compare uintegers. Operands must be the same type. The operation returns a boolean. ``` uint(v: 12345600) == uint(v: 12345601) // Returns false uint(v: 2) > uint(v: -2) // Returns false ``` #### Related * [uint() function](/flux/v0/stdlib/universe/uint/) * [toUInt() function](/flux/v0/stdlib/universe/touint/) * [hex.uint() function](/flux/v0/stdlib/contrib/bonitoo-io/hex/uint/) * [bitwise package](/flux/v0/stdlib/experimental/bitwise/) [basic types](/flux/v0/tags/basic-types/)[numeric types](/flux/v0/tags/numeric-types/)[data types](/flux/v0/tags/data-types/) | _time | _value (float) | | --- | --- | | _time | _value (float) | | 2021-01-01T00:00:00Z | 1.23 | | 2021-01-01T02:00:00Z | 4.56 | | 2021-01-01T03:00:00Z | -7.89 | | 2021-01-01T04:00:00Z | 10.11 | | _time | _value (uint) | | --- | --- | | _time | _value (uint) | | 2021-01-01T00:00:00Z | 1 | | 2021-01-01T02:00:00Z | 4 | | 2021-01-01T03:00:00Z | 18446744073709551609 | | 2021-01-01T04:00:00Z | 10 | | _time | index (string) | | --- | --- | | _time | index (string) | | 2021-01-01T00:00:00Z | 100010024 | | 2021-01-01T02:00:00Z | 100050213 | | 2021-01-01T03:00:00Z | 200130763 | | 2021-01-01T04:00:00Z | 101420099 | | _time | index (uint) | | --- | --- | | _time | index (uint) | | 2021-01-01T00:00:00Z | 100010024 | | 2021-01-01T02:00:00Z | 100050213 | | 2021-01-01T03:00:00Z | 200130763 | | 2021-01-01T04:00:00Z | 101420099 | --- # Work with composite data types Source: https://docs.influxdata.com/flux/v0/data-types/composite/ Flux **composite types** are types constructed from basic types. Flux supports the following composite types: * [Record](#record) * [Array](#array) * [Dictionary](#dictionary) * [Function](#function) ### [Record](/flux/v0/data-types/composite/record/) A **record** type is a set of key-value pairs. Learn how to work with record types in Flux. ```js {foo: "bar", baz: 123.4, quz: -2} {"Company Name": "ACME", "Street Address": "123 Main St.", id: 1123445} ``` [Read more ](/flux/v0/data-types/composite/record/) ### [Array](/flux/v0/data-types/composite/array/) An **array** type is an ordered sequence of values of the same type. Learn how to work with arrays in Flux. ```js ["1st", "2nd", "3rd"] [1.23, 4.56, 7.89] [10, 25, -15] ``` [Read more ](/flux/v0/data-types/composite/array/) ### [Dictionary](/flux/v0/data-types/composite/dict/) A **dictionary** type is a collection of key-value pairs with keys of the same type and values of the same type. Learn how to work with dictionaries in Flux. ```js [0: "Sun", 1: "Mon", 2: "Tue"] ["red": "#FF0000", "green": "#00FF00", "blue": "#0000FF"] [1.0: {stable: 12, latest: 12}, 1.1: {stable: 3, latest: 15}] ``` [Read more ](/flux/v0/data-types/composite/dict/) ### [Function](/flux/v0/data-types/composite/function/) A **function** type is a set of parameters that perform an operation. Learn how to work with functions in flux. ``` () => 1 (a, b) => a + b (a, b, c=2) => { d = a + b return d / c } ``` [Read more ](/flux/v0/data-types/composite/function/) --- # Work with arrays Source: https://docs.influxdata.com/flux/v0/data-types/composite/array/ An **array** type is an ordered sequence of values of the same type. * [Array syntax](#array-syntax) * [Reference values in an array](#reference-values-in-an-array) * [Operate on arrays](#operate-on-arrays) ## Array syntax An array literal contains a sequence of values (also known as elements) enclosed in square brackets (`[]`). Values are comma-separated and must be the same type. ##### Example arrays ```js ["1st", "2nd", "3rd"] [1.23, 4.56, 7.89] [10, 25, -15] ``` ## Reference values in an array Use **bracket notation** to reference reference a value in an array. Flux arrays use **zero-based indexing**. Provide the index of the value to reference. ``` arr = ["1st", "2nd", "3rd"] arr[0] // Returns 1st arr[2] // Returns 3rd ``` ## Operate on arrays * [Iterate over an array](#iterate-over-an-array) * [Check if a value exists in an array](#check-if-a-value-exists-in-an-array) * [Get the length of an array](#get-the-length-of-an-array) * [Create a stream of tables from an array](#create-a-stream-of-tables-from-an-array) * [Compare arrays](#compare-arrays) * [Filter an array](#filter-an-array) * [Merge two arrays](#merge-two-arrays) * [Return the string representation of an array](#return-the-string-representation-of-an-array) * [Include the string representation of an array in a table](#include-the-string-representation-of-an-array-in-a-table) ### Iterate over an array 1. Import the [`experimental/array` package](/flux/v0/stdlib/experimental/array/). 2. Use [`array.map`](/flux/v0/stdlib/experimental/array/map/) to iterate over elements in an array, apply a function to each element, and then return a new array. ``` import "experimental/array" a = [ {fname: "John", lname: "Doe", age: 42}, {fname: "Jane", lname: "Doe", age: 40}, {fname: "Jacob", lname: "Dozer", age: 21}, ] a |> array.map(fn: (x) => ({statement: "${x.fname} ${x.lname} is ${x.age} years old."})) // Returns // [ // {statement: "John Doe is 42 years old."}, // {statement: "Jane Doe is 40 years old."}, // {statement: "Jacob Dozer is 21 years old."} // ] ``` ### Check if a value exists in an array Use the [`contains` function](/flux/v0/stdlib/universe/contains/) to check if a value exists in an array. ``` names = ["John", "Jane", "Joe", "Sam"] contains(value: "Joe", set: names) // Returns true ``` ### Get the length of an array Use the [`length` function](/flux/v0/stdlib/universe/length/) to get the length of an array (number of elements in the array). ``` names = ["John", "Jane", "Joe", "Sam"] length(arr: names) // Returns 4 ``` ### Create a stream of tables from an array 1. Import the [`array` package](/flux/v0/stdlib/array/). 2. Use [`array.from()`](/flux/v0/stdlib/array/from/) to return a[stream of tables](/flux/v0/get-started/data-model/#stream-of-tables). The input array must be an array of [records](/flux/v0/data-types/composite/record/). Each key-value pair in the record represents a column and its value. ```js import "array" arr = [ {fname: "John", lname: "Doe", age: "37"}, {fname: "Jane", lname: "Doe", age: "32"}, {fname: "Jack", lname: "Smith", age: "56"}, ] array.from(rows: arr) ``` ##### Output |fname|lname|age| |-----|-----|---| |John | Doe |37 | |Jane | Doe |32 | |Jack |Smith|56 | ### Compare arrays Use the `==` [comparison operator](/flux/v0/spec/operators/#comparison-operators)to check if two arrays are equal. Equality is based on values, their type, and order. ``` [1,2,3,4] == [1,3,2,4] // Returns false [12300.0, 34500.0] == [float(v: "1.23e+04"), float(v: "3.45e+04")] // Returns true ``` ### Filter an array 1. Import the [`experimental/array` package](/flux/v0/stdlib/experimental/array/). 2. Use [`array.filter`](/flux/v0/stdlib/experimental/array/filter/) to iterate over and evaluate elements in an array with a predicate function and then return a new array with only elements that match the predicate. ``` import "experimental/array" a = [1, 2, 3, 4, 5] a |> array.filter(fn: (x) => x >= 3) // Returns [3, 4, 5] ``` ### Merge two arrays 1. Import the [`experimental/array` package](/flux/v0/stdlib/experimental/array/). 2. Use [`array.concat`](/flux/v0/stdlib/experimental/array/concat/) to merge two arrays. ``` import "experimental/array" a = [1, 2, 3] b = [4, 5, 6] a |> array.concat(v: b) // Returns [1, 2, 3, 4, 5, 6] ``` ### Return the string representation of an array Use [`display()`](/flux/v0/stdlib/universe/display/) to return Flux literal representation of an array as a string. ``` arr = [1, 2, 3] display(v: arr) // Returns "[1, 2, 3]" ``` ### Include the string representation of an array in a table Use [`display()`](/flux/v0/stdlib/universe/display/) to return Flux literal representation of an array as a string and include it as a column value. ```js import "sampledata" sampledata.string() |> map(fn: (r) => ({_time: r._time, exampleArray: display(v: [r.tag, r._value])})) ``` #### Output | \_time *(time)* |exampleArray *(string)*| |--------------------|-----------------------| |2021-01-01T00:00:00Z| [t1, smpl\_g9qczs] | |2021-01-01T00:00:10Z| [t1, smpl\_0mgv9n] | |2021-01-01T00:00:20Z| [t1, smpl\_phw664] | |2021-01-01T00:00:30Z| [t1, smpl\_guvzy4] | |2021-01-01T00:00:40Z| [t1, smpl\_5v3cce] | |2021-01-01T00:00:50Z| [t1, smpl\_s9fmgy] | |2021-01-01T00:00:00Z| [t2, smpl\_b5eida] | |2021-01-01T00:00:10Z| [t2, smpl\_eu4oxp] | |2021-01-01T00:00:20Z| [t2, smpl\_5g7tz4] | |2021-01-01T00:00:30Z| [t2, smpl\_sox1ut] | |2021-01-01T00:00:40Z| [t2, smpl\_wfm757] | |2021-01-01T00:00:50Z| [t2, smpl\_dtn2bv] | #### Related * [length() function](/flux/v0/stdlib/universe/length/) * [array package](/flux/v0/stdlib/array/) [composite types](/flux/v0/tags/composite-types/)[data types](/flux/v0/tags/data-types/) | fname | lname | age | | --- | --- | --- | | fname | lname | age | | John | Doe | 37 | | Jane | Doe | 32 | | Jack | Smith | 56 | | _time (time) | exampleArray (string) | | --- | --- | | _time (time) | exampleArray (string) | | 2021-01-01T00:00:00Z | [t1, smpl_g9qczs] | | 2021-01-01T00:00:10Z | [t1, smpl_0mgv9n] | | 2021-01-01T00:00:20Z | [t1, smpl_phw664] | | 2021-01-01T00:00:30Z | [t1, smpl_guvzy4] | | 2021-01-01T00:00:40Z | [t1, smpl_5v3cce] | | 2021-01-01T00:00:50Z | [t1, smpl_s9fmgy] | | 2021-01-01T00:00:00Z | [t2, smpl_b5eida] | | 2021-01-01T00:00:10Z | [t2, smpl_eu4oxp] | | 2021-01-01T00:00:20Z | [t2, smpl_5g7tz4] | | 2021-01-01T00:00:30Z | [t2, smpl_sox1ut] | | 2021-01-01T00:00:40Z | [t2, smpl_wfm757] | | 2021-01-01T00:00:50Z | [t2, smpl_dtn2bv] | --- # Work with dictionaries Source: https://docs.influxdata.com/flux/v0/data-types/composite/dict/ A **dictionary** type is a collection of key-value pairs with keys of the same type and values of the same type. * [Dictionary syntax](#dictionary-syntax) * [Reference dictionary values](#reference-dictionary-values) * [Operate on dictionaries](#operate-on-dictionaries) ## Dictionary syntax A **dictionary** literal contains a set of key-value pairs (also known as elements) enclosed in square brackets (`[]`). Elements are comma-delimited. Keys must all be the same type. Values must all be the same type. Keys are associated to values by a colon (`:`). ##### Example dictionaries ```js [0: "Sun", 1: "Mon", 2: "Tue"] ["red": "#FF0000", "green": "#00FF00", "blue": "#0000FF"] [1.0: {stable: 12, latest: 12}, 1.1: {stable: 3, latest: 15}] ``` ## Reference dictionary values Flux dictionaries are **key-indexed**. To reference values in a dictionary: 1. Import the [`dict` package](/flux/v0/stdlib/dict/). 2. Use [`dict.get()`](/flux/v0/stdlib/dict/get/) and provide the following parameters: * **dict**: Dictionary to reference * **key**: Key to reference * **default**: Default value to return if the key does not exist ``` import "dict" positions = [ "Manager": "Jane Doe", "Asst. Manager": "Jack Smith", "Clerk": "John Doe", ] dict.get(dict: positions, key: "Manager", default: "Unknown position") // Returns Jane Doe dict.get(dict: positions, key: "Teller", default: "Unknown position") // Returns Unknown position ``` ## Operate on dictionaries * [Create a dictionary from a list](#create-a-dictionary-from-a-list) * [Insert a key-value pair into a dictionary](#insert-a-key-value-pair-into-a-dictionary) * [Remove a key-value pair from a dictionary](#remove-a-key-value-pair-from-a-dictionary) * [Return the string representation of a dictionary](#return-the-string-representation-of-a-dictionary) * [Include the string representation of a dictionary in a table](#include-the-string-representation-of-a-dictionary-in-a-table) ### Create a dictionary from a list 1. Import the [`dict` package](/flux/v0/stdlib/dict/). 2. Use [`dict.fromList()`](/flux/v0/stdlib/dict/fromlist/) to create a dictionary from an **[array](/flux/v0/data-types/composite/array/) of [records](/flux/v0/data-types/composite/record/)**. Each record must have a **key** and **value** property. ``` import "dict" list = [{key: "k1", value: "v1"}, {key: "k2", value: "v2"}] dict.fromList(pairs: list) // Returns [k1: v1, k2: v2] ``` ### Insert a key-value pair into a dictionary 1. Import the [`dict` package](/flux/v0/stdlib/dict/). 2. Use [`dict.insert()`](/flux/v0/stdlib/dict/insert/) to insert a key-value pair into a dictionary. If the key already exists, it’s overwritten with the new value. ``` import "dict" exampleDict = ["k1": "v1", "k2": "v2"] dict.insert(dict: exampleDict, key: "k3", value: "v3") // Returns [k1: v1, k2: v2, k3: v3] ``` ### Remove a key-value pair from a dictionary 1. Import the [`dict` package](/flux/v0/stdlib/dict/). 2. Use [`dict.remove()`](/flux/v0/stdlib/dict/remove/) to remove a key-value pair from a dictionary. ``` import "dict" exampleDict = ["k1": "v1", "k2": "v2"] dict.remove(dict: exampleDict, key: "k2") // Returns [k1: v1] ``` ### Return the string representation of a dictionary Use [`display()`](/flux/v0/stdlib/universe/display/) to return Flux literal representation of a dictionary as a string. ``` x = ["a": 1, "b": 2, "c": 3] display(v: x) // Returns "[a: 1, b: 2, c: 3]" ``` ### Include the string representation of a dictionary in a table Use [`display()`](/flux/v0/stdlib/universe/display/) to return Flux literal representation of a dictionary as a string and include it as a column value. ```js import "sampledata" sampledata.string() |> map(fn: (r) => ({_time: r._time, exampleDict: display(v: ["tag": r.tag, "value":r._value])})) ``` #### Output | \_time *(time)* | exampleDict *(string)* | |--------------------|------------------------------| |2021-01-01T00:00:00Z|[tag: t1, value: smpl\_g9qczs]| |2021-01-01T00:00:10Z|[tag: t1, value: smpl\_0mgv9n]| |2021-01-01T00:00:20Z|[tag: t1, value: smpl\_phw664]| |2021-01-01T00:00:30Z|[tag: t1, value: smpl\_guvzy4]| |2021-01-01T00:00:40Z|[tag: t1, value: smpl\_5v3cce]| |2021-01-01T00:00:50Z|[tag: t1, value: smpl\_s9fmgy]| |2021-01-01T00:00:00Z|[tag: t2, value: smpl\_b5eida]| |2021-01-01T00:00:10Z|[tag: t2, value: smpl\_eu4oxp]| |2021-01-01T00:00:20Z|[tag: t2, value: smpl\_5g7tz4]| |2021-01-01T00:00:30Z|[tag: t2, value: smpl\_sox1ut]| |2021-01-01T00:00:40Z|[tag: t2, value: smpl\_wfm757]| |2021-01-01T00:00:50Z|[tag: t2, value: smpl\_dtn2bv]| #### Related * [dict package](/flux/v0/stdlib/dict/) [composite types](/flux/v0/tags/composite-types/)[data types](/flux/v0/tags/data-types/) | _time (time) | exampleDict (string) | | --- | --- | | _time (time) | exampleDict (string) | | 2021-01-01T00:00:00Z | [tag: t1, value: smpl_g9qczs] | | 2021-01-01T00:00:10Z | [tag: t1, value: smpl_0mgv9n] | | 2021-01-01T00:00:20Z | [tag: t1, value: smpl_phw664] | | 2021-01-01T00:00:30Z | [tag: t1, value: smpl_guvzy4] | | 2021-01-01T00:00:40Z | [tag: t1, value: smpl_5v3cce] | | 2021-01-01T00:00:50Z | [tag: t1, value: smpl_s9fmgy] | | 2021-01-01T00:00:00Z | [tag: t2, value: smpl_b5eida] | | 2021-01-01T00:00:10Z | [tag: t2, value: smpl_eu4oxp] | | 2021-01-01T00:00:20Z | [tag: t2, value: smpl_5g7tz4] | | 2021-01-01T00:00:30Z | [tag: t2, value: smpl_sox1ut] | | 2021-01-01T00:00:40Z | [tag: t2, value: smpl_wfm757] | | 2021-01-01T00:00:50Z | [tag: t2, value: smpl_dtn2bv] | --- # Work with functions Source: https://docs.influxdata.com/flux/v0/data-types/composite/function/ A **function** type is a set of parameters that perform an operation. * [Function syntax](#function-syntax) * [Define functions](#define-functions) ## Function syntax A Flux **function** literal contains the following: * Zero or more parameters enclosed in parentheses (`()`) * Parameters are comma separated * Parameters must be named (no positional params) * Optionally assign a default value for each parameter with the `=`[assignment operator](/flux/v0/spec/operators/#assignment-operators). Parameters without a default value require user input and are considered **required parameters**. * `=>` [arrow operator](/flux/v0/spec/operators/#function-operators) to pass parameters into the function body. * Function body to define function operations and return a response. ##### Example functions ``` // Function that returns the value 1 () => 1 // Function that returns the sum of a and b (a, b) => a + b // Function with default values (x=1, y=1) => x * y // Function with a block body (a, b, c) => { d = a + b return d / c } ``` ## Define functions *For information about defining custom functions, see [Define custom functions](/flux/v0/define-functions/).* #### Related * [Define custom functions](/flux/v0/define-functions/) [composite types](/flux/v0/tags/composite-types/)[data types](/flux/v0/tags/data-types/) --- # Work with records Source: https://docs.influxdata.com/flux/v0/data-types/composite/record/ A **record** type is a set of key-value pairs (also known as properties). Keys (also known as labels) are strings. Values can be any data type. Each property can have a different value type. * [Record syntax](#record-syntax) * [Reference values in a record](#reference-values-in-a-record) * [Operate on records](#operate-on-records) ## Record syntax A **record** literal contains a set of key-value pairs (properties) enclosed in curly brackets (`{}`). Properties are comma-delimited.**Property keys must be strings** and can optionally be enclosed in double quotes (`"`). If a property key contains whitespace characters or only numeric characters, you must enclose the property key in double quotes. Property keys are associated to values by a colon (`:`).**Values can be any type**. ##### Example records ```js {foo: "bar", baz: 123.4, quz: -2} {"Company Name": "ACME", "Street Address": "123 Main St.", id: 1123445} ``` ## Reference values in a record Flux records are **key-indexed**. To reference values in a record, use **dot notation** or **bracket notation**and specify the key to reference. * [Dot notation](#dot-notation) * [Bracket notation](#bracket-notation) * [Reference nested records](#reference-nested-records) * [Reference keys statically](#reference-keys-statically) ### Dot notation Specify the record to access followed by a period (`.`) and the property key. ``` c = {name: "John Doe", address: "123 Main St.", id: 1123445} c.name // Returns John Doe c.id // Returns 1123445 ``` ### Bracket notation Specify the record to access followed by the property key enclosed in double quotes and square brackets (`[""]`). > [!Note] > Use bracket notation to access keys with special or whitespace characters. ``` c = {"Company Name": "ACME", "Street Address": "123 Main St.", id: 1123445} c["Company Name"] // Returns ACME c["id"] // Returns 1123445 ``` ### Reference nested records To reference nested records, use chained dot or bracket notation for each nested level. ``` customer = { name: "John Doe", address: { street: "123 Main St.", city: "Pleasantville", state: "New York" } } customer.address.street // Returns 123 Main St. customer["address"]["city"] // Returns Pleasantville customer["address"].state // Returns New York ``` ### Reference keys statically **Record keys can only be referenced statically**, meaning you cannot dynamically specify a key to access. For example: ``` key = "foo" o = {foo: "bar", baz: 123.4} o.key // Error: type error: record is missing label key ``` *To dynamically reference keys in a composite type, consider using a[dictionary](/flux/v0/data-types/composite/dict/).* ## Operate on records * [Extend a record](#extend-a-record) * [List keys in a record](#list-keys-in-a-record) * [Compare records](#compare-records) * [Return the string representation of a record](#return-the-string-representation-of-a-record) * [Include the string representation of a record in a table](#include-the-string-representation-of-a-record-in-a-table) ### Extend a record Use the **`with` operator** to extend a record. The `with` operator overwrites record properties if the specified keys exists or adds the new properties if the keys do not exist. ``` c = {name: "John Doe", id: 1123445} {c with spouse: "Jane Doe", pet: "Spot"} // Returns {id: 1123445, name: John Doe, pet: Spot, spouse: Jane Doe} ``` ### List keys in a record 1. Import the [`experimental` package](/flux/v0/stdlib/experimental/). 2. Use [`experimental.objectKeys`](/flux/v0/stdlib/experimental/objectkeys/)to return an array of keys in a record. ``` import "experimental" c = {name: "John Doe", id: 1123445} experimental.objectKeys(o: c) // Returns [name, id] ``` ### Compare records Use the `==` [comparison operator](/flux/v0/spec/operators/#comparison-operators)to check if two records are equal. Equality is based on keys, their values, and types. ``` {id: 1, msg: "hello"} == {id: 1, msg: "goodbye"} // Returns false {foo: 12300.0, bar: 34500.0} == {bar: float(v: "3.45e+04"), foo: float(v: "1.23e+04")} // Returns true ``` ### Return the string representation of a record Use [`display()`](/flux/v0/stdlib/universe/display/) to return the Flux literal representation of a record as a string. ``` x = {a: 1, b: 2, c: 3} display(v: x) // Returns "{a: 1, b: 2, c: 3}" ``` ### Include the string representation of a record in a table Use [`display()`](/flux/v0/stdlib/universe/display/) to return the Flux literal representation of a record as a string and include it as a column value. ```js import "sampledata" sampledata.string() |> map(fn: (r) => ({_time: r._time, exampleRecord: display(v: {tag: r.tag, value:r._value})})) ``` #### Output | \_time *(time)* | exampleRecord *(string)* | |--------------------|------------------------------| |2021-01-01T00:00:00Z|{tag: t1, value: smpl\_g9qczs}| |2021-01-01T00:00:10Z|{tag: t1, value: smpl\_0mgv9n}| |2021-01-01T00:00:20Z|{tag: t1, value: smpl\_phw664}| |2021-01-01T00:00:30Z|{tag: t1, value: smpl\_guvzy4}| |2021-01-01T00:00:40Z|{tag: t1, value: smpl\_5v3cce}| |2021-01-01T00:00:50Z|{tag: t1, value: smpl\_s9fmgy}| |2021-01-01T00:00:00Z|{tag: t2, value: smpl\_b5eida}| |2021-01-01T00:00:10Z|{tag: t2, value: smpl\_eu4oxp}| |2021-01-01T00:00:20Z|{tag: t2, value: smpl\_5g7tz4}| |2021-01-01T00:00:30Z|{tag: t2, value: smpl\_sox1ut}| |2021-01-01T00:00:40Z|{tag: t2, value: smpl\_wfm757}| |2021-01-01T00:00:50Z|{tag: t2, value: smpl\_dtn2bv}| [composite types](/flux/v0/tags/composite-types/)[data types](/flux/v0/tags/data-types/) | _time (time) | exampleRecord (string) | | --- | --- | | _time (time) | exampleRecord (string) | | 2021-01-01T00:00:00Z | {tag: t1, value: smpl_g9qczs} | | 2021-01-01T00:00:10Z | {tag: t1, value: smpl_0mgv9n} | | 2021-01-01T00:00:20Z | {tag: t1, value: smpl_phw664} | | 2021-01-01T00:00:30Z | {tag: t1, value: smpl_guvzy4} | | 2021-01-01T00:00:40Z | {tag: t1, value: smpl_5v3cce} | | 2021-01-01T00:00:50Z | {tag: t1, value: smpl_s9fmgy} | | 2021-01-01T00:00:00Z | {tag: t2, value: smpl_b5eida} | | 2021-01-01T00:00:10Z | {tag: t2, value: smpl_eu4oxp} | | 2021-01-01T00:00:20Z | {tag: t2, value: smpl_5g7tz4} | | 2021-01-01T00:00:30Z | {tag: t2, value: smpl_sox1ut} | | 2021-01-01T00:00:40Z | {tag: t2, value: smpl_wfm757} | | 2021-01-01T00:00:50Z | {tag: t2, value: smpl_dtn2bv} | --- # Work with dynamic types Source: https://docs.influxdata.com/flux/v0/data-types/dynamic/ A **dynamic** type is a wrapper for data whose type is not known until runtime. Dynamic types help when working with data from external sources (like JSON) that support types that do not have an equivalent Flux type. * [Parse JSON into Flux types](#parse-json-into-flux-types) * [Dynamic type syntax](#dynamic-type-syntax) * [Reference values in a dynamic type](#reference-values-in-a-dynamic-type) * [Operate on dynamic types](#operate-on-dynamic-types) > [!Note] > #### Dynamic types are not supported in tables > > **Dynamic types are not supported in Flux tables.**To include a dynamic value in a Flux table, you must[cast the dynamic type to a Flux basic type](#basic-types). > For a full example of casting dynamic types to basic types and including them > in a table, see [Include dynamic types in a table](#include-dynamic-types-in-a-table). ## Parse JSON into Flux types The primary (but not exclusive) use case for dynamic types is converting JSON data into native Flux types; specifically Flux [arrays](/flux/v0/data-types/composite/array/)and [records](/flux/v0/data-types/composite/record/). Because of strict typing rules in Flux, JSON data doesn’t always gracefully parse into native Flux types. The most common reason is that Flux arrays require all children to be the same type. JSON arrays allow elements to be different types. With Flux records (the corollary of a JSON object), the properties in the record are part of the record’s type. If you have a JSON array of objects where the objects’ schemas are different, the array cannot be parsed as a Flux array because the types of the records in the array do not match. [](#view-examples-of-json-arrays-that-cannot-be-directly-parsed-into-flux-arrays) View examples of JSON arrays that cannot be directly parsed into Flux arrays #### Array of scalar values The following array is a valid JSON array, but an invalid Flux array because each element in the array is a different type. ```json ["three", 2, true] ``` #### Array of objects The following array is a valid JSON array, but an invalid Flux array. The schemas of the objects in the array do not match, so when converted to Flux records, their types do not match and the array is invalid. ```json [ {"first-name": "John", "last-name": "Doe", "age": 42}, {"first-name": "Jane", "last-name": "Doe"}, {"first-name": "James", "last-name": "Doe", "age": 15} ] ``` The dynamic type provides a way to resolve the differences between JSON and Flux types. ## Dynamic type syntax Flux does not provide a literal syntax for dynamic types. To cast a value to a dynamic type: 1. Import the [`experimental/dynamic` package](/flux/v0/stdlib/experimental/dynamic/). 2. Use [`dynamic.dynamic()`](/flux/v0/stdlib/experimental/dynamic/dynamic/) to convert a value to a dynamic type. ``` import "experimental/dynamic" dynamic.dynamic(v: "Example string") // Returns dynamic(Example string) ``` ## Reference values in a dynamic type Use bracket and dot notation to reference values in dynamic records and arrays. Use the `exists` operator to check if a dynamic type contains a non-null value. * [Reference values in a dynamic record](#reference-values-in-a-dynamic-record) * [Reference values in a dynamic array](#reference-values-in-a-dynamic-array) * [Ensure a dynamic type contains a non-null value](#ensure-a-dynamic-type-contains-a-non-null-value) ### Reference values in a dynamic record ``` import "experimental/dynamic" record = {one: 1, two: 2, three: 3} dynamicRecord = dynamic.dynamic(v: record) dynamicRecord.one // Returns dynamic(1) dynamicRecord["two"] // Returns dynamic(2) ``` ### Reference values in a dynamic array ``` import "experimental/dynamic" arr = ["a", "b", "c"] dynamicArr = dynamic.asArray(v: dynamic.dynamic(v: arr)) dynamicArr[0] // Returns dynamic(a) ``` ### Ensure a dynamic type contains a non-null value Use the `exists` operator to check if a dynamic type contains a non-null value. If you attempt to access members of a null dynamic value, Flux returns an error.`exists` lets you guard against errors caused by attempting to access members in null dynamic values. [](#view-examples-of-using-exists-to-check-for-non-null-dynamic-types) View examples of using `exists` to check for non-null dynamic types ``` import "experimental/dynamic" import "internal/debug" dynamicRecord = dynamic.dynamic(v: {one: 1, two: 2, three: 3}) dynamicNull = dynamic.dynamic(v: debug.null()) exists dynamicRecord // Returns true exists dynamicNull // Returns false ``` ##### Accessing members of dynamic types ``` dynamicRecord.one // Returns dynamic(1) dynamicRecord.four // Returns dynamic() dynamicNull.one // Error: cannot access property "one" on value of type invalid ``` ## Operate on dynamic types * [Convert dynamic types to Flux types](#convert-dynamic-types-to-flux-types) * [Basic types](#basic-types) * [Composite types](#composite-types) * [Include dynamic types in a table](#include-dynamic-types-in-a-table) * [Convert a JSON array to a Flux table](#convert-a-json-array-to-a-flux-table) * [Encode a dynamic type as JSON](#encode-a-dynamic-type-as-json) * [Encode a dynamic record as JSON](#encode-a-dynamic-record-as-json) * [Encode a dynamic array of different basic types as JSON](#encode-a-dynamic-array-of-different-basic-types-as-json) ### Convert dynamic types to Flux types #### Basic types [String](#string)[Integer](#integer)[UInteger](#uinteger)[Float](#float)[Boolean](#boolean)[Duration](#duration)[Time](#time)[Bytes](#bytes)[Regexp](#regexp) Use [`string()`](/flux/v0/stdlib/universe/string/) to convert a dynamic type to a string.`string()` returns the string representation of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: "string") string(v: dynamicValue) // Returns "string" ``` Use [`int()`](/flux/v0/stdlib/universe/int/) to convert a dynamic type to an integer.`int()` returns the [integer equivalent](/flux/v0/data-types/basic/int/#convert-data-types-to-integers)of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: "12") int(v: dynamicValue) // Returns 12 ``` Use [`uint()`](/flux/v0/stdlib/universe/uint/) to convert a dynamic type to an unsigned integer (UInteger).`uint()` returns the [UInteger equivalent](/flux/v0/data-types/basic/uint/#convert-data-types-to-uintegers)of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: "12") uint(v: dynamicValue) // Returns 12 ``` Use [`float()`](/flux/v0/stdlib/universe/float/) to convert a dynamic type to a floating point value.`float()` returns the [float equivalent](/flux/v0/data-types/basic/float/#convert-data-types-to-floats)of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: "12.1") float(v: dynamicValue) // Returns 12.1 ``` Use [`bool()`](/flux/v0/stdlib/universe/bool/) to convert a dynamic type to a boolean value.`bool()` returns the [boolean equivalent](/flux/v0/data-types/basic/bool/#convert-data-types-to-booleans)of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: "true") bool(v: dynamicValue) // Returns true ``` Use [`duration()`](/flux/v0/stdlib/universe/duration/) to convert a dynamic type to a duration value.`duration()` returns the [duration equivalent](/flux/v0/data-types/basic/duration/#convert-data-types-to-durations)of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: 3000000000) duration(v: dynamicValue) // Returns 3s ``` Use [`time()`](/flux/v0/stdlib/universe/time/) to convert a dynamic type to a time value.`time()` returns the [time equivalent](/flux/v0/data-types/basic/time/#convert-data-types-to-time)of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: 1640995200000000000) time(v: dynamicValue) // Returns 2022-01-01T00:00:00.000000000Z ``` Use [`bytes()`](/flux/v0/stdlib/universe/bytes/) to convert a dynamic type to a byte-encoded string.`bytes()` returns the [bytes equivalent](/flux/v0/data-types/basic/bytes/#convert-data-types-to-bytes)of the dynamic value. ``` import "experimental/dynamic" dynamicValue = dynamic.dynamic(v: "Hello world!") bytes(v: dynamicValue) // Returns 0x48656c6c6f20776f726c6421 ``` 1. Use [`string()`](/flux/v0/stdlib/universe/string/) to convert a dynamic type to a string. 2. Import the [`regexp` package](/flux/v0/stdlib/regexp/) and use[`regexp.compile()`](/flux/v0/stdlib/regexp/compile/) to convert the string value to a regular expression type. ``` import "experimental/dynamic" import "regexp" dynamicValue = dynamic.dynamic(v: "^[abc][123]{1,}") stringValue = string(v: dynamicValue) regexp.compile(v: stringValue) // Returns /^[abc][123]{1,}/ ``` #### Composite types Dynamic composite types will almost always come from working with a byte-encoded JSON string. All the examples below assume this. [Array](#array)[Record](#record) **To convert a JSON array to a Flux array:** 1. Import the following packages: * [array](/flux/v0/stdlib/array/) * [experimental/dynamic](/flux/v0/stdlib/experimental/dynamic/) 2. Use [`dynamic.jsonParse()`](/flux/v0/stdlib/experimental/dynamic/jsonparse/)to parse a byte-encoded JSON string into a dynamic type. 3. Use [`dynamic.asArray()`](/flux/v0/stdlib/experimental/dynamic/asarray/)to convert the dynamic-typed array into an array of dynamic types. 4. Use [`array.map()`](/flux/v0/stdlib/array/map/) to iterate over each element in the array and explicitly [cast dynamic types to basic types](#basic-types). [](#view-example-with-an-array-of-scalar-values) View example with an array of scalar values ##### JSON array of scalar values ```json ["3", 2, true] ``` ##### Convert a JSON array of scalar values to a Flux array ``` import "array" import "experimental/dynamic" json = jsonBytes // Byte-encoded JSON above parsed = dynamic.jsonParse(data: json) parsed |> dynamic.asArray() |> array.map(fn: (x) => int(v: x)) // Returns [3, 2, 1] ``` [](#view-example-with-an-array-of-json-objects) View example with an array of JSON objects ##### JSON array of objects ```json [ {"first-name": "John", "last-name": "Doe", "age": 42}, {"first-name": "Jane", "last-name": "Doe"}, {"first-name": "James", "last-name": "Doe", "age": 15} ] ``` ##### Convert a JSON array of objects to a Flux array ``` import "array" import "experimental/dynamic" json = jsonBytes // Byte-encoded JSON above parsed = dynamic.jsonParse(data: json) parsed |> dynamic.asArray() |> array.map( fn: (x) => ({ fname: string(v: x["first-name"]), lname: string(v: x["last-name"]), age: int(v: x.age) }), ) // Returns [ // {age: 42, fname: John, lname: Doe}, // {age: , fname: Jane, lname: Doe}, // {age: 15, fname: James, lname: Doe} // ] ``` **To convert a JSON object to a Flux record:** 1. Import the [`experimental/dynamic` package](/flux/v0/stdlib/experimental/dynamic/) 2. Use [`dynamic.jsonParse()`](/flux/v0/stdlib/experimental/dynamic/jsonparse/)to parse a byte-encoded JSON string into a dynamic type. 3. Define a new record and [cast each property of the dynamic type to a basic type](#basic-types). ##### JSON object ```json {"first-name": "John", "last-name": "Doe", "age": 42} ``` ##### Convert a JSON object to a Flux record ``` import "experimental/dynamic" json = jsonBytes // Byte-encoded JSON above parsed = dynamic.jsonParse(data: json) newRecord = { fname: string(v: parsed["first-name"]), lname: string(v: parsed["last-name"]), age: int(v: parsed.age) } // newRecord returns {age: 42, fname: John, lname: Doe} ``` ### Check the type of a value inside of a dynamic type Use [`dynamic.isType()`](/flux/v0/stdlib/experimental/dynamic/istype/) to check the type of a value inside of a dynamic type. The following example uses the [`http/requests` package](/flux/v0/stdlib/http/requests/)and the [Fruityvice API](https://www.fruityvice.com/) to return information about apples as a JSON object. [](#view-the-returned-json-object) View the returned JSON object ```json { "genus": "Malus", "name": "Apple", "id": 6, "family": "Rosaceae", "order": "Rosales", "nutritions": { "carbohydrates": 11.4, "protein": 0.3, "fat": 0.4, "calories": 52, "sugar": 10.3 } } ``` ``` import "experimental/dynamic" response = requests.get(url: "https://www.fruityvice.com/api/fruit/apple") parsed = dynamic.jsonParse(data: response.body) dynamic.isType(v: parsed.genus, type: "string") // Returns true dynamic.isType(v: parsed.nutritions, type: "array") // Returns false dynamic.isType(v: parsed.nutritions, type: "object") // Returns true ``` ### Include dynamic types in a table **Dynamic types are not supported in Flux tables.**To include a dynamic value in a Flux table,[cast the dynamic type to a Flux basic type](#basic-types). The following example uses [`array.from()`](/flux/v0/stdlib/array/from/) to build and ad hoc table using dynamic types. Each dynamic type must be cast to a Flux basic type when defining the row record. ```js import "array" import "experimental/dynamic" dynamicString = dynamic.dynamic(v: "one") dynamicInt = dynamic.dynamic(v: 1) dynamicFloat = dynamic.dynamic(v: 1.0) dynamicBool = dynamic.dynamic(v: true) array.from( rows: [ { string: string(v: dynamicString), int: int(v: dynamicInt), float: float(v: dynamicFloat), bool: bool(v: dynamicBool), }, ], ) ``` [](#view-output-table) View output table |string|int|float|bool| |------|---|-----|----| | one | 1 | 1.0 |true| ### Convert a JSON array to a Flux table 1. Import the following packages: * [array](/flux/v0/stdlib/array/) * [experimental/dynamic](/flux/v0/stdlib/experimental/dynamic/) 2. Use [`dynamic.jsonParse()`](/flux/v0/stdlib/experimental/dynamic/jsonparse/)to parse the the JSON response body returned from `requests.get()` into a Flux dynamic type. Define a variable to capture the parsed JSON. The example below uses the `parsed` variable. 3. Use [`dynamic.asArray()`](/flux/v0/stdlib/experimental/dynamic/asarray/)to convert the dynamic type returned by `dynamic.jsonParse()` to a dynamic array. Define a variable to capture the dynamic array. The example below uses the `fruit` variable. 4. Use [`array.map()`](/flux/v0/stdlib/array/map/) to do the following: * Iterate over each dynamic record in the dynamic array and flatten nested records. Flux tables do not support nested [records](/flux/v0/data-types/composite/record/)(the corollary of a JSON object). * Explicitly [cast dynamic values in each dynamic record to a Flux basic type](#basic-types). The following example uses the [`http/requests` package](/flux/v0/stdlib/http/requests/)and the [Fruityvice API](https://www.fruityvice.com/) to return information about various fruit as JSON and then structure the returned data as a Flux table. ```js import "array" import "experimental/dynamic" import "http/requests" response = requests.get(url: "https://www.fruityvice.com/api/fruit/all") parsed = dynamic.jsonParse(data: response.body) fruit = dynamic.asArray(v: parsed) fruit_flat = fruit |> array.map( fn: (x) => ({ name: string(v: x.name), cals: int(v: x.nutritions.calories), carbs: float(v: x.nutritions.carbohydrates), fat: float(v: x.nutritions.fat), protein: float(v: x.nutritions.protein), sugar: float(v: x.nutritions.sugar), }), ) array.from(rows: fruit_flat) ``` [](#view-output-table) View output table | name |cals|carbs| fat |protein|sugar| |------------|----|-----|-----|-------|-----| | Apple | 52 |11.4 | 0.4 | 0.3 |10.3 | | Apricot | 15 | 3.9 | 0.1 | 0.5 | 3.2 | | Avocado |160 |8.53 |14.66| 2 |0.66 | | Banana | 96 | 22 | 0.2 | 1 |17.2 | | Blackberry | 40 | 9 | 0.4 | 1.3 | 4.5 | | Blueberry | 29 | 5.5 | 0.4 | 0 | 5.4 | | Cherry | 50 | 12 | 0.3 | 1 | 8 | |Dragonfruit | 60 | 9 | 1.5 | 9 | 8 | | Durian |147 |27.1 | 5.3 | 1.5 |6.75 | | Feijoa | 44 | 8 | 0.4 | 0.6 | 3 | | Fig | 74 | 19 | 0.3 | 0.8 | 16 | | Gooseberry | 44 | 10 | 0.6 | 0.9 | 0 | | Grape | 69 |18.1 |0.16 | 0.72 | 16 | | Grapes | 69 |18.1 |0.16 | 0.72 |15.48| | GreenApple | 21 | 3.1 | 0.1 | 0.4 | 6.4 | | Guava | 68 | 14 | 1 | 2.6 | 9 | | Kiwi | 61 | 15 | 0.5 | 1.1 | 9 | | Kiwifruit | 61 |14.6 | 0.5 | 1.14 | 8.9 | | Lemon | 29 | 9 | 0.3 | 1.1 | 2.5 | | Lime | 25 | 8.4 | 0.1 | 0.3 | 1.7 | |Lingonberry | 50 |11.3 |0.34 | 0.75 |5.74 | | Lychee | 66 | 17 |0.44 | 0.8 | 15 | | Mango | 60 | 15 |0.38 | 0.82 |13.7 | | Melon | 34 | 8 | 0 | 0 | 8 | | Morus | 43 | 9.8 |0.39 | 1.44 | 8.1 | | Orange | 43 | 8.3 | 0.2 | 1 | 8.2 | | Papaya | 43 | 11 | 0.4 | 0 | 1 | |Passionfruit| 97 |22.4 | 0.7 | 2.2 |11.2 | | Pear | 57 | 15 | 0.1 | 0.4 | 10 | | Persimmon | 81 | 18 | 0 | 0 | 18 | | Pineapple | 50 |13.12|0.12 | 0.54 |9.85 | | Pitahaya | 36 | 7 | 0.4 | 1 | 3 | | Plum | 46 |11.4 |0.28 | 0.7 |9.92 | |Pomegranate | 83 |18.7 | 1.2 | 1.7 |13.7 | | Raspberry | 53 | 12 | 0.7 | 1.2 | 4.4 | | Strawberry | 29 | 5.5 | 0.4 | 0.8 | 5.4 | | Tangerine | 45 | 8.3 | 0.4 | 0 | 9.1 | | Tomato | 74 | 3.9 | 0.2 | 0.9 | 2.6 | | Watermelon | 30 | 8 | 0.2 | 0.6 | 6 | ### Encode a dynamic type as JSON #### Encode a dynamic record as JSON 1. Import the `experimental/dynamic` package. 2. Use [`dynamic.dynamic()`](/flux/v0/stdlib/experimental/dynamic/dynamic/)to convert the record to a dynamic type. 3. Use [`dynamic.jsonEncode()`](/flux/v0/stdlib/experimental/dynamic/jsonencode/)to convert the dynamic record into a byte-encoded JSON string. ``` import "experimental/dynamic" dynamicRecord = dynamic.dynamic(v: {one: 1, two: 2, three: 3}) dynamic.jsonEncode(v: dynamicRecord) // Returns the following byte-encoded JSON string: // {"one":1,"three":3,"two":2} ``` #### Encode a dynamic array of different basic types as JSON Build a dynamic array where each element is a different basic type. This might be necessary if you’re send JSON data to an API that expects an array of values where each value is a different type. Values in a Flux array must be the same type, so you must build a dynamic array of dynamic types: 1. Import the `experimental/dynamic` package. 2. Use [`dynamic.dynamic()`](/flux/v0/stdlib/experimental/dynamic/dynamic/) to convert the array to a dynamic type. 3. Use `dynamic.dynamic()` to convert all values in the array to dynamic types. 4. Use [`dynamic.jsonEncode()`](/flux/v0/stdlib/experimental/dynamic/jsonencode/)to convert the dynamic array into a byte-encoded JSON string. ``` import "experimental/dynamic" arr = dynamic.dynamic( v: [ dynamic.dynamic(v: "three"), dynamic.dynamic(v: 2), dynamic.dynamic(v: true) ], ) dynamic.jsonEncode(v: arr) // Returns the following byte-encoded JSON string: // ["three", 2, true] ``` [dynamic types](/flux/v0/tags/dynamic-types/)[data types](/flux/v0/tags/data-types/) | string | int | float | bool | | --- | --- | --- | --- | | string | int | float | bool | | one | 1 | 1.0 | true | | name | cals | carbs | fat | protein | sugar | | --- | --- | --- | --- | --- | --- | | name | cals | carbs | fat | protein | sugar | | Apple | 52 | 11.4 | 0.4 | 0.3 | 10.3 | | Apricot | 15 | 3.9 | 0.1 | 0.5 | 3.2 | | Avocado | 160 | 8.53 | 14.66 | 2 | 0.66 | | Banana | 96 | 22 | 0.2 | 1 | 17.2 | | Blackberry | 40 | 9 | 0.4 | 1.3 | 4.5 | | Blueberry | 29 | 5.5 | 0.4 | 0 | 5.4 | | Cherry | 50 | 12 | 0.3 | 1 | 8 | | Dragonfruit | 60 | 9 | 1.5 | 9 | 8 | | Durian | 147 | 27.1 | 5.3 | 1.5 | 6.75 | | Feijoa | 44 | 8 | 0.4 | 0.6 | 3 | | Fig | 74 | 19 | 0.3 | 0.8 | 16 | | Gooseberry | 44 | 10 | 0.6 | 0.9 | 0 | | Grape | 69 | 18.1 | 0.16 | 0.72 | 16 | | Grapes | 69 | 18.1 | 0.16 | 0.72 | 15.48 | | GreenApple | 21 | 3.1 | 0.1 | 0.4 | 6.4 | | Guava | 68 | 14 | 1 | 2.6 | 9 | | Kiwi | 61 | 15 | 0.5 | 1.1 | 9 | | Kiwifruit | 61 | 14.6 | 0.5 | 1.14 | 8.9 | | Lemon | 29 | 9 | 0.3 | 1.1 | 2.5 | | Lime | 25 | 8.4 | 0.1 | 0.3 | 1.7 | | Lingonberry | 50 | 11.3 | 0.34 | 0.75 | 5.74 | | Lychee | 66 | 17 | 0.44 | 0.8 | 15 | | Mango | 60 | 15 | 0.38 | 0.82 | 13.7 | | Melon | 34 | 8 | 0 | 0 | 8 | | Morus | 43 | 9.8 | 0.39 | 1.44 | 8.1 | | Orange | 43 | 8.3 | 0.2 | 1 | 8.2 | | Papaya | 43 | 11 | 0.4 | 0 | 1 | | Passionfruit | 97 | 22.4 | 0.7 | 2.2 | 11.2 | | Pear | 57 | 15 | 0.1 | 0.4 | 10 | | Persimmon | 81 | 18 | 0 | 0 | 18 | | Pineapple | 50 | 13.12 | 0.12 | 0.54 | 9.85 | | Pitahaya | 36 | 7 | 0.4 | 1 | 3 | | Plum | 46 | 11.4 | 0.28 | 0.7 | 9.92 | | Pomegranate | 83 | 18.7 | 1.2 | 1.7 | 13.7 | | Raspberry | 53 | 12 | 0.7 | 1.2 | 4.4 | | Strawberry | 29 | 5.5 | 0.4 | 0.8 | 5.4 | | Tangerine | 45 | 8.3 | 0.4 | 0 | 9.1 | | Tomato | 74 | 3.9 | 0.2 | 0.9 | 2.6 | | Watermelon | 30 | 8 | 0.2 | 0.6 | 6 | --- # Define custom functions Source: https://docs.influxdata.com/flux/v0/define-functions/ Flux’s functional syntax lets you define custom functions. Learn the basics of creating your own functions. ###### On this page: * [Function definition syntax](#function-definition-syntax) * [Custom function examples](#custom-function-examples) * [Create a custom transformation](#create-a-custom-transformation) * [Custom transformation examples](#custom-transformation-examples) * [Define functions with scoped variables](#define-functions-with-scoped-variables) * [Example functions with scoped variables](#example-functions-with-scoped-variables) ## Function definition syntax The basic syntax for defining functions in Flux is as follows: ```js // Basic function definition syntax functionName = (functionParameters) => functionBody ``` * **functionName**: Name to use to execute the function. * **functionParameters**: Comma-separated list of parameters passed into the function. * **functionBody**: Operations on function parameters. ### Define parameter defaults Use the `=` assignment operator to assign a default value to function parameters in your function definition: ```js functionName = (param1=defaultVal1, param2=defaultVal2) => functionBody ``` Defaults are overridden by explicitly defining the parameter in the function call. Parameters without default values are considered **required parameters**. ## Custom function examples [](#square-a-number) Square a number ``` square = (n) => n * n square(n:3) // Returns 9 ``` [](#multiple-two-values) Multiple two values ``` multiply = (x, y) => x * y multiply(x: 2, y: 15) // Returns 30 ``` [](#calculate-n-to-the-p-power-with-default-parameters) Calculate n to the p power (with default parameters) ``` pow = (n, p=10) => n ^ p pow(n: 2) // Returns 1024 ``` ## Create a custom transformation A [transformation](/flux/v0/function-types/#transformations) is a function that takes a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)as input, operates on the input, and then outputs a new stream of tables. The [pipe-forward operator](/flux/v0/get-started/syntax-basics/#pipe-forward-operator) (`|>`) pipes data from the previous identifier or function forward into a transformation. To use piped-forward data, assign a function parameter to the[pipe-receive operator](/flux/v0/spec/operators/#function-operators) (`<-`). In the following example, the function `x()` receives piped-forwarded data and assigns it to the `t` parameter. In the function body, `t` is piped forward into other operations to generate output. ``` x = (t=<-) => t |> //... ``` ### Custom transformation examples [](#multiply-values-by-x) Multiply values by x #### Multiply values by x The following example defines a `multByX` function that multiplies the `_value` column of each input row by the `x` parameter. The example uses the [`map()` function](/flux/v0/stdlib/universe/map/) to iterate over each row, modify the `_value`, and then return the updated row. ##### Function definition ```js multByX = (tables=<-, x) => tables |> map(fn: (r) => ({r with _value: r._value * x})) ``` ##### Example usage ```js data |> multByX(x: 2.0) ``` ###### Given the following input data: |srcID|\_field|\_value| |-----|-------|-------| | t1a | foo | 1.2 | | t1a | foo | 3.4 | | t1a | foo | 5.6 | |srcID|\_field|\_value| |-----|-------|-------| | t2b | foo | 0.8 | | t2b | foo | 1.9 | | t2b | foo | 2.7 | ###### The example above returns: |srcID|\_field|\_value| |-----|-------|-------| | t1a | foo | 2.4 | | t1a | foo | 6.8 | | t1a | foo | 11.2 | |srcID|\_field|\_value| |-----|-------|-------| | t2b | foo | 1.6 | | t2b | foo | 3.8 | | t2b | foo | 5.4 | [](#calculate-speed) Calculate speed #### Calculate speed The following example defines a `speed` function that calculates speed using an`elapsed` and `distance` column in input tables. The example uses the [`map()` function](/flux/v0/stdlib/universe/map/) to iterate over each row, calculate the speed per specified unit of distance, and then return the updated row with a new `speed` column. ##### Function definition ```js speed = (tables=<-, unit="m") => tables |> map( fn: (r) => { elapsedHours = float(v: int(v: duration(v: r.elapsed))) / float(v: int(v: 1h)) distance = float(v: r.distance) speed = distance / elapsedHours return {r with speed: "${speed} ${unit}ph"} }, ) ``` ##### Example usage ```js data |> speed() ``` ##### Given the following input data: |id |elapsed|distance| |---|-------|--------| |t1 | 1h15m | 101 | |t2 | 1h32m | 138 | |t3 | 56m | 112 | ##### The example above returns: |id |elapsed|distance| speed | |---|-------|--------|--------| |t1 | 1h15m | 101 |88.8 mph| |t2 | 1h32m | 138 | 90 mph | |t3 | 56m | 112 |120 mph | ## Define functions with scoped variables To create custom functions with variables scoped to the function, 1. Enclose your [function body](#function-definition-syntax) in a[block (`{}`)](/flux/v0/spec/blocks/). 2. Use a `return` statement to return a specific variable. ```js functionName = (param) => { exampleVar = "foo" return exampleVar } ``` ### Example functions with scoped variables [](#return-an-alert-level-based-on-a-value) Return an alert level based on a value #### Return an alert level based on a value The following function uses conditional logic to return an alert level based on a numeric input value: ``` alertLevel = (v) => { level = if float(v: v) >= 90.0 then "crit" else if float(v: v) >= 80.0 then "warn" else if float(v: v) >= 65.0 then "info" else "ok" return level } alertLevel(v: 87.3) // Returns "warn" ``` [](#convert-a-hex-color-code-to-a-name) Convert a HEX color code to a name #### Convert a HEX color code to a name The following function converts a hexadecimal (HEX) color code to the equivalent HTML color name. The functions uses the [Flux dictionary package](/flux/v0/stdlib/dict/)to create a dictionary of HEX codes and their corresponding names. ``` import "dict" hexName = (hex) => { hexNames = dict.fromList( pairs: [ {key: "#00ffff", value: "Aqua"}, {key: "#000000", value: "Black"}, {key: "#0000ff", value: "Blue"}, {key: "#ff00ff", value: "Fuchsia"}, {key: "#808080", value: "Gray"}, {key: "#008000", value: "Green"}, {key: "#00ff00", value: "Lime"}, {key: "#800000", value: "Maroon"}, {key: "#000080", value: "Navy"}, {key: "#808000", value: "Olive"}, {key: "#800080", value: "Purple"}, {key: "#ff0000", value: "Red"}, {key: "#c0c0c0", value: "Silver"}, {key: "#008080", value: "Teal"}, {key: "#ffffff", value: "White"}, {key: "#ffff00", value: "Yellow"}, ], ) name = dict.get(dict: hexNames, key: hex, default: "No known name") return name } hexName(hex: "#000000") // Returns "Black" hexName(hex: "#8b8b8b") // Returns "No known name" ``` #### Related * [Work with functions](/flux/v0/data-types/composite/function/) | srcID | _field | _value | | --- | --- | --- | | srcID | _field | _value | | t1a | foo | 1.2 | | t1a | foo | 3.4 | | t1a | foo | 5.6 | | srcID | _field | _value | | --- | --- | --- | | srcID | _field | _value | | t2b | foo | 0.8 | | t2b | foo | 1.9 | | t2b | foo | 2.7 | | srcID | _field | _value | | --- | --- | --- | | srcID | _field | _value | | t1a | foo | 2.4 | | t1a | foo | 6.8 | | t1a | foo | 11.2 | | srcID | _field | _value | | --- | --- | --- | | srcID | _field | _value | | t2b | foo | 1.6 | | t2b | foo | 3.8 | | t2b | foo | 5.4 | | id | elapsed | distance | | --- | --- | --- | | id | elapsed | distance | | t1 | 1h15m | 101 | | t2 | 1h32m | 138 | | t3 | 56m | 112 | | id | elapsed | distance | speed | | --- | --- | --- | --- | | id | elapsed | distance | speed | | t1 | 1h15m | 101 | 88.8 mph | | t2 | 1h32m | 138 | 90 mph | | t3 | 56m | 112 | 120 mph | --- # Function type signatures Source: https://docs.influxdata.com/flux/v0/function-type-signatures/ A **function type signature** describes a function’s input parameters and types, and the function’s output type. Use type signatures to identify data types expected by function parameters and to understand a function’s expected output. * [Function type signature structure](#function-type-signature-structure) * [Parameter notation](#parameter-notation) * [Type variables](#type-variables) * [Type notation](#type-notation) * [Stream types](#stream-types) * [Basic types](#basic-types) * [Composite types](#composite-types) * [Type constraints](#type-constraints) * [Example function type signatures](#example-function-type-signatures) ## Function type signature structure ```js (parameter: type) => output-type ``` ### Parameter notation Parameter notation indicates specific behaviors of function parameters. ``` ? // Optional parameter <- // Pipe receive – indicates the parameter that, by default, represents // the piped-forward value ``` ## Type variables Flux type signatures use **type variables** to represent unique types in the signature. A type variable is [polymorphic](/flux/v0/spec/types/#polymorphism), meaning it can be one of many types, and may be constrained by [type constraints](#type-constraints). Type variables use the following identifier patterns: ``` A B C t11 // etc. ``` ## Type notation * [Stream types](#stream-types) * [Basic types](#basic-types) * [Composite types](#composite-types) ### Stream types Type signatures identify stream types ([streams of tables](/flux/v0/get-started/data-model/#stream-of-tables)) using the `stream[A]` syntax where `A` is a unique [type variable](#type-variables). Stream types may included specific column names and column types. ```js // Stream of tables stream[A] // Stream of tables with specific columns, but inferred column types. stream[{col1: A, col2: B}] // Stream of tables additional or required "count" column with an // explicit integer type. stream[{A with count: int}] ``` ### Basic types Type signatures identify [basic types](/flux/v0/data-types/basic/) with the following type identifiers: ``` bool // boolean type bytes // bytes type duration // duration type float // float type int // integer type regexp // regular expression type string // string type time // time type uint // unsigned integer type ``` ### Composite types Type signatures identify Flux [composite types](/flux/v0/data-types/composite/)with the following syntaxes: ``` [A] // array type [B: A] // dictionary type (param: A) => B // function type {_value: int} // record type ``` ## Type constraints Some function parameters are “polymorphic” and can support multiple data types. Polymorphic parameters are bound by **type constraints**, which define what types can be used. Type signatures indicate type constraints for specific values using the`where A: Constraint` syntax. For example, the following type signature describes a function that takes a single parameter, `v` and returns and integer.`v` can be any type that satisfies the Timeable constraint (duration or time). ```js (v: A) => int where A: Timeable ``` For more information about the different type constraints and the types each supports, see [Type constraints](/flux/v0/spec/types/#type-constraints). ## Example function type signatures * [Function without parameters](#function-without-parameters) * [Function with parameters](#function-with-parameters) * [Pass-through transformation](#pass-through-transformation) * [Basic transformation](#basic-transformation) * [Transformation that adds a column with an explicit type](#transformation-that-adds-a-column-with-an-explicit-type) #### Function without parameters The following type signature describes a function that: * Has no parameters * Returns a time value ```js () => time ``` #### Function with parameters The following type signature describes a function that: * Has two parameters of type `A`: * multiplier *(Optional)* * v (Required) * Returns a value the same type as the two input parameters ```js (?multiplier: A, v: A) => A ``` #### Pass-through transformation The following type signature describes a[transformation](/flux/v0/function-types/#transformations) that: * Takes a stream of tables of type `A` as piped-forward input * Returns the input stream of tables with an unmodified type ```js (<-tables: stream[A]) => stream[A] ``` #### Basic transformation The following type signature describes a[transformation](/flux/v0/function-types/#transformations) that: * Takes a stream of tables of type `A` as piped-forward input * Has an `fn` parameter with a function type * `fn` uses type `A` as input and returns type `B` * Returns a new, modified stream of tables of type `B` ```js (<-tables: stream[A], fn: (r: A) => B,) => stream[B] ``` #### Transformation that adds a column with an explicit type The following type signature describes a[transformation](/flux/v0/function-types/#transformations) that: * Takes a stream of tables of type `A` as piped-forward input * Has a required **tag** parameter of type `B` * The `B` type is constrained by the Stringable constraint * Returns a new, modified stream of tables of type `A` that includes a **tag**column with string values ```js (<-tables: stream[A], tag: B) => stream[{A with tag: string}] where B: Stringable ``` #### Related * [Work with Flux data types](/flux/v0/data-types/) * [Type constraints](/flux/v0/spec/types/#type-constraints) --- # Flux function types and categories Source: https://docs.influxdata.com/flux/v0/function-types/ Flux functions share a set of behaviors or traits that define how the function works. This types and categories lists below are not all-inclusive, but covers distinct and important function behaviors. * [Function types](#function-types) * [Function categories](#function-categories) > [!Note] > The icon indicates the function is experimental. ## Function types * [Inputs](#inputs) * [Outputs](#outputs) * [Transformations](#transformations) * [Aggregates](#aggregates) * [Selectors](#selectors) * [Dynamic queries](#dynamic-queries) ### Inputs Flux input functions return data from data sources. The following input functions are available: * [array.from()](/flux/v0/stdlib/array/from/) * [bigtable.from()](/flux/v0/stdlib/experimental/bigtable/from/) * [clickhouse.query()](/flux/v0/stdlib/contrib/qxip/clickhouse/query/) * [csv.from()](/flux/v0/stdlib/csv/from/) * [from()](/flux/v0/stdlib/influxdata/influxdb/from/) * [from()](/flux/v0/stdlib/contrib/jsternberg/influxdb/from/) * [generate.from()](/flux/v0/stdlib/generate/from/) * [http.get()](/flux/v0/stdlib/experimental/http/get/) *– (deprecated)* * [influxdb.select()](/flux/v0/stdlib/contrib/jsternberg/influxdb/select/) * [iox.from()](/flux/v0/stdlib/experimental/iox/from/) * [iox.sql()](/flux/v0/stdlib/experimental/iox/sql/) * [logql.query\_range()](/flux/v0/stdlib/contrib/qxip/logql/query_range/) * [monitor.logs()](/flux/v0/stdlib/influxdata/influxdb/monitor/logs/) * [prometheus.scrape()](/flux/v0/stdlib/experimental/prometheus/scrape/) * [query.inBucket()](/flux/v0/stdlib/experimental/query/inbucket/) * [requests.do()](/flux/v0/stdlib/http/requests/do/) * [requests.do()](/flux/v0/stdlib/experimental/http/requests/do/) *– (deprecated)* * [requests.get()](/flux/v0/stdlib/http/requests/get/) * [requests.get()](/flux/v0/stdlib/experimental/http/requests/get/) *– (deprecated)* * [requests.post()](/flux/v0/stdlib/http/requests/post/) * [requests.post()](/flux/v0/stdlib/experimental/http/requests/post/) *– (deprecated)* * [socket.from()](/flux/v0/stdlib/socket/from/) * [usage.from()](/flux/v0/stdlib/experimental/usage/from/) * [v1.json()](/flux/v0/stdlib/influxdata/influxdb/v1/json/) ### Outputs Flux output functions yield results or send data to a specified output destination. The following output functions are are available: * [experimental.to()](/flux/v0/stdlib/experimental/to/) *– (deprecated)* * [influxdb.wideTo()](/flux/v0/stdlib/influxdata/influxdb/wideto/) * [kafka.to()](/flux/v0/stdlib/kafka/to/) * [mqtt.to()](/flux/v0/stdlib/experimental/mqtt/to/) * [tickscript.alert()](/flux/v0/stdlib/contrib/bonitoo-io/tickscript/alert/) * [to()](/flux/v0/stdlib/influxdata/influxdb/to/) * [yield()](/flux/v0/stdlib/universe/yield/) ### Transformations Flux transformations take a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables)as input, transform the data in some way, and output a stream of tables. Transformations cover a broad range of functions, but the following categorizations highlight important behaviors associated with specific transformation functions. * [Aggregates](#aggregates) * [Selectors](#selectors) > [!Note] > ##### aggregateWindow helper function > > The [`aggregateWindow()` function](/flux/v0/stdlib/universe/aggregatewindow)windows or groups data by time and applies an aggregate or selector function > to input tables.**All aggregate and selector functions** work with `aggregateWindow()`. #### Aggregates Flux aggregate functions are [transformations](#transformations) aggregate values from input tables in some way. Output tables contain a single row with the aggregated value. Aggregate transformations output a table for every input table they receive. Each output table from an aggregate function will: * Contain a single record. * Have the same [group key](/flux/v0/get-started/data-model/#group-key) as the input table. * Contain the an aggregated column. The column label will be the same as the input table. The column data type depends on the specific aggregate operation. The value of the column will be `null` if the input table is empty or the input column has only `null` values. * Drop all columns that are: * not in the group key * not the aggregated column **The following aggregate functions are available:** * [aggregate.rate()](/flux/v0/stdlib/experimental/aggregate/rate/) * [aggregateWindow()](/flux/v0/stdlib/universe/aggregatewindow/) * [count()](/flux/v0/stdlib/universe/count/) * [cov()](/flux/v0/stdlib/universe/cov/) * [covariance()](/flux/v0/stdlib/universe/covariance/) * [experimental.count()](/flux/v0/stdlib/experimental/count/) * [experimental.histogramQuantile()](/flux/v0/stdlib/experimental/histogramquantile/) * [experimental.integral()](/flux/v0/stdlib/experimental/integral/) * [experimental.mean()](/flux/v0/stdlib/experimental/mean/) * [experimental.mode()](/flux/v0/stdlib/experimental/mode/) * [experimental.quantile()](/flux/v0/stdlib/experimental/quantile/) * [experimental.skew()](/flux/v0/stdlib/experimental/skew/) * [experimental.spread()](/flux/v0/stdlib/experimental/spread/) * [experimental.stddev()](/flux/v0/stdlib/experimental/stddev/) * [experimental.sum()](/flux/v0/stdlib/experimental/sum/) * [geo.ST\_LineString()](/flux/v0/stdlib/experimental/geo/st_linestring/) * [geo.totalDistance()](/flux/v0/stdlib/experimental/geo/totaldistance/) * [integral()](/flux/v0/stdlib/universe/integral/) * [mean()](/flux/v0/stdlib/universe/mean/) * [median()](/flux/v0/stdlib/universe/median/) * [mode()](/flux/v0/stdlib/universe/mode/) * [pearsonr()](/flux/v0/stdlib/universe/pearsonr/) * [prometheus.histogramQuantile()](/flux/v0/stdlib/experimental/prometheus/histogramquantile/) * [quantile()](/flux/v0/stdlib/universe/quantile/) * [reduce()](/flux/v0/stdlib/universe/reduce/) * [skew()](/flux/v0/stdlib/universe/skew/) * [spread()](/flux/v0/stdlib/universe/spread/) * [stddev()](/flux/v0/stdlib/universe/stddev/) * [sum()](/flux/v0/stdlib/universe/sum/) * [timeWeightedAvg()](/flux/v0/stdlib/universe/timeweightedavg/) ##### Aggregate selectors The following functions are both aggregates and selectors. Each returns `n` values after performing an aggregate operation. They are categorized as [selector functions](#selectors) in this documentation: * [highestAverage()](/flux/v0/stdlib/universe/highestaverage) * [highestCurrent()](/flux/v0/stdlib/universe/highestcurrent) * [highestMax()](/flux/v0/stdlib/universe/highestmax) * [lowestAverage()](/flux/v0/stdlib/universe/lowestaverage) * [lowestCurrent()](/flux/v0/stdlib/universe/lowestcurrent) * [lowestMin()](/flux/v0/stdlib/universe/lowestmin) #### Selectors Flux selector functions are [transformations](#transformations) that return one or more record per input table. Each output table from a selector function will: * Contain one or more unmodified records. * Have the same [group key](/flux/v0/get-started/data-model/#group-key) as the input table. **The following selector functions are available:** * [aggregateWindow()](/flux/v0/stdlib/universe/aggregatewindow/) * [bottom()](/flux/v0/stdlib/universe/bottom/) * [distinct()](/flux/v0/stdlib/universe/distinct/) * [experimental.distinct()](/flux/v0/stdlib/experimental/distinct/) * [experimental.first()](/flux/v0/stdlib/experimental/first/) * [experimental.last()](/flux/v0/stdlib/experimental/last/) * [experimental.max()](/flux/v0/stdlib/experimental/max/) * [experimental.min()](/flux/v0/stdlib/experimental/min/) * [experimental.quantile()](/flux/v0/stdlib/experimental/quantile/) * [experimental.unique()](/flux/v0/stdlib/experimental/unique/) * [first()](/flux/v0/stdlib/universe/first/) * [highestAverage()](/flux/v0/stdlib/universe/highestaverage/) * [highestCurrent()](/flux/v0/stdlib/universe/highestcurrent/) * [highestMax()](/flux/v0/stdlib/universe/highestmax/) * [last()](/flux/v0/stdlib/universe/last/) * [limit()](/flux/v0/stdlib/universe/limit/) * [lowestAverage()](/flux/v0/stdlib/universe/lowestaverage/) * [lowestCurrent()](/flux/v0/stdlib/universe/lowestcurrent/) * [lowestMin()](/flux/v0/stdlib/universe/lowestmin/) * [max()](/flux/v0/stdlib/universe/max/) * [median()](/flux/v0/stdlib/universe/median/) * [min()](/flux/v0/stdlib/universe/min/) * [quantile()](/flux/v0/stdlib/universe/quantile/) * [sample()](/flux/v0/stdlib/universe/sample/) * [top()](/flux/v0/stdlib/universe/top/) * [unique()](/flux/v0/stdlib/universe/unique/) ##### Selectors and aggregates The following functions can be used as both selectors or aggregates, but they are categorized as [aggregate functions](#aggregates) in this documentation: * [median()](/flux/v0/stdlib/universe/median) * [quantile()](/flux/v0/stdlib/universe/quantile) ### Dynamic queries Flux dynamic query functions extract a table from a stream of tables and access its columns and records. For recommended usage, see [Extract scalar values](/influxdb/cloud/query-data/flux/scalar-values/). * [findColumn()](/flux/v0/stdlib/universe/findcolumn/) * [findRecord()](/flux/v0/stdlib/universe/findrecord/) * [getColumn()](/flux/v0/stdlib/universe/getcolumn/) * [getRecord()](/flux/v0/stdlib/universe/getrecord/) * [tableFind()](/flux/v0/stdlib/universe/tablefind/) ## Function categories The following categories represent high-level function behaviors. * [Filters](#filters) * [Type conversions](#type-conversions) * [Tests](#tests) * [Date/time](#datetime) * [Metadata](#metadata) * [Notification endpoints](#notification-endpoints) * [Geotemporal](#geotemporal) ### Filters Filter functions iterate over and evaluate each input row to see if it matches specified conditions. Rows that do not match the specified conditions are dropped from the output. The following filter functions are available: * [filter()](/flux/v0/stdlib/universe/filter/) * [geo.filterRows()](/flux/v0/stdlib/experimental/geo/filterrows/) * [geo.gridFilter()](/flux/v0/stdlib/experimental/geo/gridfilter/) * [geo.strictFilter()](/flux/v0/stdlib/experimental/geo/strictfilter/) * [hourSelection()](/flux/v0/stdlib/universe/hourselection/) * [query.filterFields()](/flux/v0/stdlib/experimental/query/filterfields/) * [query.filterMeasurement()](/flux/v0/stdlib/experimental/query/filtermeasurement/) * [query.fromRange()](/flux/v0/stdlib/experimental/query/fromrange/) * [range()](/flux/v0/stdlib/universe/range/) ### Type conversions Flux type conversion functions convert scalar values or columns to a specific data type. The following type conversion functions are available: * [array.toBool()](/flux/v0/stdlib/experimental/array/tobool/) * [array.toDuration()](/flux/v0/stdlib/experimental/array/toduration/) * [array.toFloat()](/flux/v0/stdlib/experimental/array/tofloat/) * [array.toInt()](/flux/v0/stdlib/experimental/array/toint/) * [array.toString()](/flux/v0/stdlib/experimental/array/tostring/) * [array.toTime()](/flux/v0/stdlib/experimental/array/totime/) * [array.toUInt()](/flux/v0/stdlib/experimental/array/touint/) * [bool()](/flux/v0/stdlib/universe/bool/) * [bytes()](/flux/v0/stdlib/universe/bytes/) * [duration()](/flux/v0/stdlib/universe/duration/) * [dynamic.asArray()](/flux/v0/stdlib/experimental/dynamic/asarray/) * [dynamic.dynamic()](/flux/v0/stdlib/experimental/dynamic/dynamic/) * [dynamic.jsonEncode()](/flux/v0/stdlib/experimental/dynamic/jsonencode/) * [dynamic.jsonParse()](/flux/v0/stdlib/experimental/dynamic/jsonparse/) * [float()](/flux/v0/stdlib/universe/float/) * [int()](/flux/v0/stdlib/universe/int/) * [iox.sqlInterval()](/flux/v0/stdlib/experimental/iox/sqlinterval/) * [json.encode()](/flux/v0/stdlib/json/encode/) * [json.parse()](/flux/v0/stdlib/experimental/json/parse/) * [regexp.compile()](/flux/v0/stdlib/regexp/compile/) * [string()](/flux/v0/stdlib/universe/string/) * [time()](/flux/v0/stdlib/universe/time/) * [toBool()](/flux/v0/stdlib/universe/tobool/) * [toFloat()](/flux/v0/stdlib/universe/tofloat/) * [toInt()](/flux/v0/stdlib/universe/toint/) * [toString()](/flux/v0/stdlib/universe/tostring/) * [toTime()](/flux/v0/stdlib/universe/totime/) * [toUInt()](/flux/v0/stdlib/universe/touint/) * [uint()](/flux/v0/stdlib/universe/uint/) ### Tests Flux testing functions test various aspects of data. Tests return either `true` or `false`, a transformed stream of tables, or, upon failure, an error. The following testing functions are available: * [dynamic.isType()](/flux/v0/stdlib/experimental/dynamic/istype/) * [testing.assertEmpty()](/flux/v0/stdlib/testing/assertempty/) * [testing.assertEquals()](/flux/v0/stdlib/testing/assertequals/) * [testing.assertEqualValues()](/flux/v0/stdlib/testing/assertequalvalues/) * [testing.assertMatches()](/flux/v0/stdlib/internal/testing/assertmatches/) * [testing.diff()](/flux/v0/stdlib/testing/diff/) * [testing.shouldError()](/flux/v0/stdlib/testing/shoulderror/) * [testing.shouldErrorWithCode()](/flux/v0/stdlib/internal/testing/shoulderrorwithcode/) * [types.isNumeric()](/flux/v0/stdlib/types/isnumeric/) * [types.isType()](/flux/v0/stdlib/types/istype/) ### Date/time Flux date/time functions return or operate on [time](/flux/v0/data-types/basic/time/)or [duration](/flux/v0/spec/types/#duration-types) values. The following data/time functions are available: * [boundaries.friday()](/flux/v0/stdlib/date/boundaries/friday/) *– (deprecated)* * [boundaries.friday()](/flux/v0/stdlib/experimental/date/boundaries/friday/) * [boundaries.monday()](/flux/v0/stdlib/date/boundaries/monday/) *– (deprecated)* * [boundaries.monday()](/flux/v0/stdlib/experimental/date/boundaries/monday/) * [boundaries.month()](/flux/v0/stdlib/date/boundaries/month/) *– (deprecated)* * [boundaries.month()](/flux/v0/stdlib/experimental/date/boundaries/month/) * [boundaries.saturday()](/flux/v0/stdlib/date/boundaries/saturday/) *– (deprecated)* * [boundaries.saturday()](/flux/v0/stdlib/experimental/date/boundaries/saturday/) * [boundaries.sunday()](/flux/v0/stdlib/date/boundaries/sunday/) *– (deprecated)* * [boundaries.sunday()](/flux/v0/stdlib/experimental/date/boundaries/sunday/) * [boundaries.thursday()](/flux/v0/stdlib/date/boundaries/thursday/) *– (deprecated)* * [boundaries.thursday()](/flux/v0/stdlib/experimental/date/boundaries/thursday/) * [boundaries.tuesday()](/flux/v0/stdlib/date/boundaries/tuesday/) *– (deprecated)* * [boundaries.tuesday()](/flux/v0/stdlib/experimental/date/boundaries/tuesday/) * [boundaries.wednesday()](/flux/v0/stdlib/date/boundaries/wednesday/) *– (deprecated)* * [boundaries.wednesday()](/flux/v0/stdlib/experimental/date/boundaries/wednesday/) * [boundaries.week()](/flux/v0/stdlib/date/boundaries/week/) *– (deprecated)* * [boundaries.week()](/flux/v0/stdlib/experimental/date/boundaries/week/) * [boundaries.yesterday()](/flux/v0/stdlib/date/boundaries/yesterday/) *– (deprecated)* * [boundaries.yesterday()](/flux/v0/stdlib/experimental/date/boundaries/yesterday/) * [date.add()](/flux/v0/stdlib/date/add/) * [date.hour()](/flux/v0/stdlib/date/hour/) * [date.microsecond()](/flux/v0/stdlib/date/microsecond/) * [date.millisecond()](/flux/v0/stdlib/date/millisecond/) * [date.minute()](/flux/v0/stdlib/date/minute/) * [date.month()](/flux/v0/stdlib/date/month/) * [date.monthDay()](/flux/v0/stdlib/date/monthday/) * [date.nanosecond()](/flux/v0/stdlib/date/nanosecond/) * [date.quarter()](/flux/v0/stdlib/date/quarter/) * [date.scale()](/flux/v0/stdlib/date/scale/) * [date.second()](/flux/v0/stdlib/date/second/) * [date.sub()](/flux/v0/stdlib/date/sub/) * [date.time()](/flux/v0/stdlib/date/time/) * [date.truncate()](/flux/v0/stdlib/date/truncate/) * [date.week()](/flux/v0/stdlib/date/week/) * [date.weekDay()](/flux/v0/stdlib/date/weekday/) * [date.year()](/flux/v0/stdlib/date/year/) * [date.yearDay()](/flux/v0/stdlib/date/yearday/) * [experimental.addDuration()](/flux/v0/stdlib/experimental/addduration/) *– (deprecated)* * [experimental.alignTime()](/flux/v0/stdlib/experimental/aligntime/) * [experimental.subDuration()](/flux/v0/stdlib/experimental/subduration/) *– (deprecated)* * [experimental.window()](/flux/v0/stdlib/experimental/window/) * [hourSelection()](/flux/v0/stdlib/universe/hourselection/) * [now()](/flux/v0/stdlib/universe/now/) * [system.time()](/flux/v0/stdlib/system/time/) * [timeShift()](/flux/v0/stdlib/universe/timeshift/) * [timezone.fixed()](/flux/v0/stdlib/timezone/fixed/) * [timezone.location()](/flux/v0/stdlib/timezone/location/) * [today()](/flux/v0/stdlib/universe/today/) * [truncateTimeColumn()](/flux/v0/stdlib/universe/truncatetimecolumn/) ### Metadata Flux metadata functions return metadata from the input stream or from an underlying data source. The following metadata functions are available: * [buckets()](/flux/v0/stdlib/influxdata/influxdb/buckets/) * [influxdb.cardinality()](/flux/v0/stdlib/influxdata/influxdb/cardinality/) * [schema.fieldKeys()](/flux/v0/stdlib/influxdata/influxdb/schema/fieldkeys/) * [schema.measurementFieldKeys()](/flux/v0/stdlib/influxdata/influxdb/schema/measurementfieldkeys/) * [schema.measurements()](/flux/v0/stdlib/influxdata/influxdb/schema/measurements/) * [schema.measurementTagKeys()](/flux/v0/stdlib/influxdata/influxdb/schema/measurementtagkeys/) * [schema.measurementTagValues()](/flux/v0/stdlib/influxdata/influxdb/schema/measurementtagvalues/) * [schema.tagKeys()](/flux/v0/stdlib/influxdata/influxdb/schema/tagkeys/) * [schema.tagValues()](/flux/v0/stdlib/influxdata/influxdb/schema/tagvalues/) * [v1.databases()](/flux/v0/stdlib/influxdata/influxdb/v1/databases/) * [v1.fieldKeys()](/flux/v0/stdlib/influxdata/influxdb/v1/fieldkeys/) *– (deprecated)* * [v1.measurementFieldKeys()](/flux/v0/stdlib/influxdata/influxdb/v1/measurementfieldkeys/) *– (deprecated)* * [v1.measurements()](/flux/v0/stdlib/influxdata/influxdb/v1/measurements/) *– (deprecated)* * [v1.measurementTagKeys()](/flux/v0/stdlib/influxdata/influxdb/v1/measurementtagkeys/) *– (deprecated)* * [v1.measurementTagValues()](/flux/v0/stdlib/influxdata/influxdb/v1/measurementtagvalues/) *– (deprecated)* * [v1.tagKeys()](/flux/v0/stdlib/influxdata/influxdb/v1/tagkeys/) *– (deprecated)* * [v1.tagValues()](/flux/v0/stdlib/influxdata/influxdb/v1/tagvalues/) *– (deprecated)* ### Notification endpoints Flux notification endpoint functions send notifications to external endpoints or services. The following notification endpoint functions are available: * [alerta.endpoint()](/flux/v0/stdlib/contrib/bonitoo-io/alerta/endpoint/) * [bigpanda.endpoint()](/flux/v0/stdlib/contrib/rhajek/bigpanda/endpoint/) * [discord.endpoint()](/flux/v0/stdlib/contrib/chobbs/discord/endpoint/) * [http.endpoint()](/flux/v0/stdlib/http/endpoint/) * [opsgenie.endpoint()](/flux/v0/stdlib/contrib/sranka/opsgenie/endpoint/) * [pagerduty.endpoint()](/flux/v0/stdlib/pagerduty/endpoint/) * [pushbullet.endpoint()](/flux/v0/stdlib/pushbullet/endpoint/) * [sensu.endpoint()](/flux/v0/stdlib/contrib/sranka/sensu/endpoint/) * [servicenow.endpoint()](/flux/v0/stdlib/contrib/bonitoo-io/servicenow/endpoint/) * [slack.endpoint()](/flux/v0/stdlib/slack/endpoint/) * [teams.endpoint()](/flux/v0/stdlib/contrib/sranka/teams/endpoint/) * [telegram.endpoint()](/flux/v0/stdlib/contrib/sranka/telegram/endpoint/) * [victorops.endpoint()](/flux/v0/stdlib/contrib/bonitoo-io/victorops/endpoint/) * [webexteams.endpoint()](/flux/v0/stdlib/contrib/sranka/webexteams/endpoint/) * [zenoss.endpoint()](/flux/v0/stdlib/contrib/bonitoo-io/zenoss/endpoint/) ### Geotemporal Flux geotemporal functions are designed to work with geotemporal data (geographic location over time). The following geotemporal functions are available: * [geo.asTracks()](/flux/v0/stdlib/experimental/geo/astracks/) * [geo.filterRows()](/flux/v0/stdlib/experimental/geo/filterrows/) * [geo.getGrid()](/flux/v0/stdlib/experimental/geo/getgrid/) * [geo.getLevel()](/flux/v0/stdlib/experimental/geo/getlevel/) * [geo.gridFilter()](/flux/v0/stdlib/experimental/geo/gridfilter/) * [geo.groupByArea()](/flux/v0/stdlib/experimental/geo/groupbyarea/) * [geo.s2CellIDToken()](/flux/v0/stdlib/experimental/geo/s2cellidtoken/) * [geo.s2CellLatLon()](/flux/v0/stdlib/experimental/geo/s2celllatlon/) * [geo.shapeData()](/flux/v0/stdlib/experimental/geo/shapedata/) * [geo.ST\_Contains()](/flux/v0/stdlib/experimental/geo/st_contains/) * [geo.ST\_Distance()](/flux/v0/stdlib/experimental/geo/st_distance/) * [geo.ST\_DWithin()](/flux/v0/stdlib/experimental/geo/st_dwithin/) * [geo.ST\_Intersects()](/flux/v0/stdlib/experimental/geo/st_intersects/) * [geo.ST\_Length()](/flux/v0/stdlib/experimental/geo/st_length/) * [geo.ST\_LineString()](/flux/v0/stdlib/experimental/geo/st_linestring/) * [geo.stContains()](/flux/v0/stdlib/experimental/geo/stcontains/) * [geo.stDistance()](/flux/v0/stdlib/experimental/geo/stdistance/) * [geo.stLength()](/flux/v0/stdlib/experimental/geo/stlength/) * [geo.strictFilter()](/flux/v0/stdlib/experimental/geo/strictfilter/) * [geo.toRows()](/flux/v0/stdlib/experimental/geo/torows/) * [geo.totalDistance()](/flux/v0/stdlib/experimental/geo/totaldistance/) #### Related * [Flux standard library](/flux/v0/stdlib/) --- # The future of Flux Source: https://docs.influxdata.com/flux/v0/future-of-flux/ Flux is in maintenance mode and is not supported in InfluxDB 3 due to the broad demand for native SQL and the continued growth and adoption of InfluxQL. InfluxData continues to support Flux for InfluxDB 1.x and 2.x, and you can continue using it without changing your code. If interested in transitioning to InfluxDB 3 and you want to future-proof your code, we suggest using InfluxQL. As we developed InfluxDB 3, our top priority was improving performance at the database layer: faster ingestion, better compression, enhanced querying, and more scalability. However, this meant we couldn’t bring everything forward from v2. As InfluxDB 3 is a ground-up rewrite of the database in a new language (from Go to Rust), we couldn’t bring Flux forward to v3. * [What do you mean by Flux is in maintenance mode?](#what-do-you-mean-by-flux-is-in-maintenance-mode) * [Is Flux going to End-of-Life?](#is-flux-going-to-end-of-life) * [What alternatives do you have for Flux Tasks?](#what-alternatives-do-you-have-for-flux-tasks) ## What do you mean by Flux is in maintenance mode? We still support Flux, but are not actively developing any new Flux features. We will continue to provide security patches and will address any critical defects through the maintenance period. Our focus is our latest database engine, InfluxDB 3, and its associated products. ## Is Flux going to End-of-Life? No, we will continue to support Flux for the foreseeable future. We will continue to support our customers who have invested in Flux and have built apps that use it. You can continue using Flux, but if you want to future-proof your code, we recommend using InfluxQL or SQL. ## What alternatives do you have for Flux tasks? If moving to InfluxDB 3, you can’t bring Flux tasks because InfluxDB 3 doesn’t support Flux natively. When you move to v3, you will need to rewrite your tasks using whatever technologies your team prefers. However, if you’re using tasks for downsampling specifically, the storage performance in v3 is much better so you may no longer need tasks for this functionality. --- # Get started with Flux Source: https://docs.influxdata.com/flux/v0/get-started/ Flux is a **functional data scripting** language designed to unify querying, processing, analyzing, and acting on data into a single syntax. ## Flux overview To understand how Flux works conceptually, consider the process of treating water. Water is pulled from a source, limited by demand, piped through a series of stations to modify (remove sediment, purify, and so on), and delivered in a consumable state. ## Basic Flux query Like treating water, a Flux query does the following: 1. Retrieves a specified amount of data from a source. 2. Filters data based on time or column values. 3. Processes and shapes data into expected results. 4. Returns the result. To see how to retrieve data from a source, select the data source: InfluxDB, CSV, or PostgreSQL. [InfluxDB](#influxdb)[CSV](#csv)[PostgreSQL](#postgresql) ```js from(bucket: "example-bucket") |> range(start: -1d) |> filter(fn: (r) => r._measurement == "example-measurement") |> mean() |> yield(name: "_results") ``` ```js import "csv" csv.from(file: "path/to/example/data.csv") |> range(start: -1d) |> filter(fn: (r) => r._measurement == "example-measurement") |> mean() |> yield(name: "_results") ``` ```js import "sql" sql.from( driverName: "postgres", dataSourceName: "postgresql://user:password@localhost", query: "SELECT * FROM TestTable", ) |> filter(fn: (r) => r.UserID == "123ABC456DEF") |> mean(column: "purchase_total") |> yield(name: "_results") ``` Each example includes the following functions (in the order listed): * [`from()`](/flux/v0/stdlib/influxdata/influxdb/from/) to retrieve data from the data source. * [Pipe-forward operator (`|>`)](/flux/v0/get-started/syntax-basics/#pipe-forward-operator)to send the output of each function to the next function as input. * [`range()`](/flux/v0/stdlib/universe/range/), [`filter()`](/flux/v0/stdlib/universe/filter/), or both to filter data based on column values. * [`mean()`](/flux/v0/stdlib/universe/mean/) to calculate the average of values returned from the data source. * [`yield()`](/flux/v0/stdlib/universe/yield/) to yield results to the user. *For detailed information about basic Flux queries, see [Flux query basics](/flux/v0/get-started/query-basics/).* [Flux data model](/flux/v0/get-started/data-model/) #### Related --- # Flux data model Source: https://docs.influxdata.com/flux/v0/get-started/data-model/ To get the most out of using Flux to process your data, you must understand how Flux structures and operates on data. The **Flux data model** comprises the following: * [Stream of tables](#stream-of-tables) * [Table](#table) * [Column](#column) * [Row](#row) * [Group key](#group-key) | | | | |---|---|---| | | | | | | | | | | | | | | | | |---|---|---| | | | | | | | | | | | | | | | | |---|---|---| | | | | | | | | | | | | #### Stream of tables A **stream of tables** is a collection of zero or more [tables](#table). Data sources return results as a stream of tables. #### Table A **table** is a collection of [columns](#column) partitioned by [group key](#group-key). #### Column A **column** is a collection of values of the same [basic type](#)that contains one value for each [row](#row). #### Row A **row** is a collection of associated [column](#column) values. #### Group key A **group key** defines which columns to use to group tables in a stream of tables. Each table in a stream of tables represents a unique **group key instance**. All rows in a table contain the same values for each group key column. ##### Example group key A group key can be represented by an array of column labels. ``` [_measurement, facility, _field] ``` ##### Example group key instances Group key instances (unique to each table) include key-value pairs that identify each column name in the table that has the same value. The following are examples of group key instances in a stream of tables with three separate tables. Each represents a table containing data for a unique location: ``` [_measurement: "production", facility: "us-midwest", _field: "apq"] [_measurement: "production", facility: "eu-central", _field: "apq"] [_measurement: "production", facility: "ap-east", _field: "apq"] ``` An **empty group key** groups all data in a stream of tables into a single table. *For an example of how group keys work, see the [Table grouping example](#table-grouping-example) below.* ## Data sources determine data structure The Flux data model is separate from the queried data source model. Queried sources return data structured into columnar tables. The table structure and columns included depends on the data source. For example, InfluxDB returns data grouped by [series](/influxdb/v2/reference/glossary/#series), so each table in the returned stream of tables represents a unique series. However, [SQL data sources](/flux/v0/stdlib/sql/from/) return a stream of tables with a single table and an empty group key. ### Column labels beginning with underscores Some data sources return column labels prefixed with an underscore (`_`). This is a Flux convention used to identify important or reserved column names. While the underscore doesn’t change the functionality of the column, many functions in the [Flux standard library](/flux/v0/stdlib/) expect or require these specific column names. ## Operate on tables At its core, Flux operates on tables. Flux [transformations](/flux/v0/function-types/#transformations) take a stream of tables as input, but operate on each table individually. For example, aggregate transformations like [`sum()`](/flux/v0/stdlib/universe/sum/), output a stream of tables containing one table for each corresponding input table: | | | | |---|---|---| | | | | | | | | | | | | | | | | |---|---|---| | | | | | | | | | | | | | | | | |---|---|---| | | | | | | | | | | | | `|> sum()` | | | | |---|---|---| | | | | | | | | |---|---|---| | | | | | | | | |---|---|---| | | | | ## Restructure tables All tables in a stream of tables are defined by their [group key](#group-key). To change how data is partitioned or grouped into tables, use functions such as[`group()`](/flux/v0/stdlib/universe/group/) or [`window()`](/flux/v0/stdlib/universe/window/)to modify group keys in a stream of tables. ```js data |> group(columns: ["foo", "bar"], mode: "by") ``` ### Table grouping example The tables below represent data returned from InfluxDB with the following schema: * `example` measurement * `loc` tag with two values * `sensorID` tag with two values * `temp` and `hum` fields To modify the group key and see how the sample data is partitioned into new tables, select columns to group by: * \_time * \_measurement * loc * sensorID * \_field * \_value ``` data |> group(columns: ["_measurement", "loc", "sensorID", "_field"]) ``` [Get started with Flux](/flux/v0/get-started/)[Flux syntax basics](/flux/v0/get-started/syntax-basics/) #### Related | | | | | --- | --- | --- | | | | | | | | | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | | | | | | --- | --- | --- | | | | | | | | | --- # Flux query basics Source: https://docs.influxdata.com/flux/v0/get-started/query-basics/ Most Flux queries follow the same basic structure. Familiarize yourself with the basic concepts and steps to use when querying data with Flux. * [Basic query structure](#basic-query-structure) * [Write a basic query](#write-a-basic-query) ## Basic query structure The majority of basic Flux queries include the following steps: * [Source](#source) * [Filter](#filter) * [Shape](#shape-data) * [Process](#process) ``` from(bucket: "example-bucket") // ── Source |> range(start: -1d) // ── Filter on time |> filter(fn: (r) => r._field == "foo") // ── Filter on column values |> group(columns: ["sensorID"]) // ── Shape |> mean() // ── Process ``` ### Source Flux [input functions](/flux/v0/function-types/#inputs) retrieve data from a data source. All input functions return a [stream of tables](/flux/v0/get-started/data-model/#stream-of-tables). Flux supports multiple data sources including, time series databases (such as **InfluxDB** and **Prometheus**), relational databases (such as **MySQL** and **PostgreSQL**), CSV, and more. * For more information about supported data sources, see [Query data sources](/flux/v0/query-data/). * For a list of input functions, see [Function types and categories – Inputs](/flux/v0/function-types/#inputs). ### Filter Filter functions iterate over and evaluate each input row to see if it matches specified conditions. Rows that meet the conditions are included in the function output. Rows that do not meet the specified conditions are dropped. Flux provides the following primary filter functions: * [`range()`](/flux/v0/stdlib/universe/range/): filter data based on time. * [`filter()`](/flux/v0/stdlib/universe/filter/): filter data based on column values.`filter()` uses a [predicate function](/flux/v0/get-started/syntax-basics/#predicate-functions) defined in the`fn` parameter to evaluate input rows. Each row is passed into the predicate function as a **record**, `r`, containing key-value pairs for each column in the row. Other filter functions are also available. For more information, see [Function types and categories – Filters](/flux/v0/function-types/#filters). ### Shape data Many queries need to modify the structure of data to prepare it for processing. Common data-shaping tasks include [regrouping data](/flux/v0/get-started/data-model/#restructure-tables)by column values or by time or pivoting column values into rows. Functions that reshape data include the following: * [`group()`](/flux/v0/stdlib/universe/group/): modify group keys * [`window()`](/flux/v0/stdlib/universe/window/): modify `_start` and `_stop` values of rows to group data by time * [`pivot()`](/flux/v0/stdlib/universe/pivot/): pivot column values into rows * [`drop()`](/flux/v0/stdlib/universe/drop/): drop specific columns * [`keep()`](/flux/v0/stdlib/universe/keep/): keep specific columns and drop all others ### Process Processing data can take on many forms, and includes the following types of operations: * **Aggregate data**: aggregate all rows of an input table into a single row. For information, see [Function types and categories - Aggregates](/flux/v0/function-types/#aggregates). * **Select specific data points**: return specific rows from each input table. For example, return the first or last row, the row with the highest or lowest value, and more. For information, see [Function types and categories - Selectors](/flux/v0/function-types/#selectors). * **Rewrite rows**: use [`map()`](/flux/v0/stdlib/universe/map/) to rewrite each input row. Transform values with mathematic operations, process strings, dynamically add new columns, and more. * **Send notifications**: evaluate data and use Flux notification endpoint functions to send notifications to external services. For information, see [Function types and categories- Notification endpoints](/flux/v0/function-types/#notification-endpoints). > [!Note] > #### aggregateWindow helper function > > [`aggregateWindow()`](/flux/v0/stdlib/universe/aggregatewindow/) is a helper function > that both **shapes and processes data**. > The function windows and groups data by time, and then applies an [aggregate](/flux/v0/function-types/#aggregates)or [selector](/flux/v0/function-types/#selectors) function to the restructured tables. ## Write a basic query Use [InfluxDB sample data](/influxdb/v2/reference/sample-data/) to write a basic Flux query that queries data, filters the data by time and column values, and then applies an [aggregate](/flux/v0/function-types/#aggregates). > [!Note] > Use the [InfluxDB Data Explorer](/influxdb/cloud/query-data/execute-queries/data-explorer/)or the [Flux REPL](/influxdb/v2/tools/flux-repl/#build-the-repl)to build and execute the following basic query. 1. Import the [`influxdata/influxdb/sample` package](/flux/v0/stdlib/influxdata/influxdb/sample/)and use the [`sample.data()` function](/flux/v0/stdlib/influxdata/influxdb/sample/data/)to load the `airSensor` sample dataset. ``` import "influxdata/influxdb/sample" sample.data(set: "airSensor") ``` `sample.data()` returns data as if it was queried from InfluxDB. To actually query data from InfluxDB, replace `sample.data()` with the[`from()` function](/flux/v0/stdlib/influxdata/influxdb/from/). 2. Pipe the returned data forward into [`range()`](/flux/v0/stdlib/universe/range/)to filter the data by time. Return data from the last hour. ``` import "influxdata/influxdb/sample" sample.data(set: "airSensor") |> range(start: -1h) ``` 3. Use [`filter()`](/flux/v0/stdlib/universe/filter/) to filter rows based on column values. In this example, return only rows that include values for the `co` field. The field name is stored in the `_field` column. ``` import "influxdata/influxdb/sample" sample.data(set: "airSensor") |> range(start: -1h) |> filter(fn: (r) => r._field == "co") ``` 4. Use [`mean()`](/flux/v0/stdlib/universe/mean/) to calculate the average value in each input table. Because InfluxDB groups data by [series](/influxdb/cloud/reference/glossary/#series),`mean()` returns a table for each unique `sensor_id` containing a single row with the average value in the `_value` column. ``` import "influxdata/influxdb/sample" sample.data(set: "airSensor") |> range(start: -1h) |> filter(fn: (r) => r._field == "co") |> mean() ``` 5. Use [`group()`](/flux/v0/stdlib/universe/group) to [restructure tables](/flux/v0/get-started/data-model/#restructure-tables)into a single table: ``` import "influxdata/influxdb/sample" sample.data(set: "airSensor") |> range(start: -1h) |> filter(fn: (r) => r._field == "co") |> mean() |> group() ``` Results from this basic query should be similar to the following: > [!Note] > `_start` and `_stop` columns have been omitted. |\_field|\_measurement|sensor\_id| \_value | |-------|-------------|----------|-------------------| | co | airSensors | TLM0100 |0.42338714381053716| | co | airSensors | TLM0101 |0.4223251339463061 | | co | airSensors | TLM0102 |0.8543452859060252 | | co | airSensors | TLM0103 |0.2782783780205422 | | co | airSensors | TLM0200 | 4.612143110484339 | | co | airSensors | TLM0201 | 0.297474366047375 | | co | airSensors | TLM0202 |0.3336370208486757 | | co | airSensors | TLM0203 |0.4948166816959906 | [Flux syntax basics](/flux/v0/get-started/syntax-basics/) #### Related | _field | _measurement | sensor_id | _value | | --- | --- | --- | --- | | _field | _measurement | sensor_id | _value | | co | airSensors | TLM0100 | 0.42338714381053716 | | co | airSensors | TLM0101 | 0.4223251339463061 | | co | airSensors | TLM0102 | 0.8543452859060252 | | co | airSensors | TLM0103 | 0.2782783780205422 | | co | airSensors | TLM0200 | 4.612143110484339 | | co | airSensors | TLM0201 | 0.297474366047375 | | co | airSensors | TLM0202 | 0.3336370208486757 | | co | airSensors | TLM0203 | 0.4948166816959906 | --- # Flux syntax basics Source: https://docs.influxdata.com/flux/v0/get-started/syntax-basics/ Flux, at its core, is a scripting language designed specifically for working with data. This guide walks through how Flux handles a few simple expressions. ###### On this page * [Pipe-forward operator](#pipe-forward-operator) * [Simple expressions](#simple-expressions) * [Predicate expressions](#predicate-expressions) * [Variables](#variables) * [Data types](#data-types) * [Basic types](#basic-types) * [Composite Types](#composite-types) * [Records](#records) * [Arrays](#arrays) * [Dictionaries](#dictionaries) * [Functions](#functions) * [Regular expression types](#regular-expression-types) * [View the string representation of any Flux type](#view-the-string-representation-of-any-flux-type) * [Packages](#packages) * [Examples of basic syntax](#examples-of-basic-syntax) * [Define data stream variables](#define-data-stream-variables) * [Define custom functions](#define-custom-functions) ## Pipe-forward operator The **pipe-forward operator** (`|>`) sends the output of one function as input to the next function. In the [water treatment metaphor](/flux/v0/get-started/#flux-overview), the pipe-forward operator is the pipe that carries water (or data) through the pipeline. ```js data |> someFunction() |> anotherFunction() ``` ## Simple expressions Flux supports basic expressions. For example: ``` 1 + 1 // Returns 2 10 * 3 // Returns 30 (12.0 + 18.0) / (2.0 ^ 2.0) + (240.0 % 55.0) // Returns 27.5 "John " + "Doe " + "is here!" // Returns John Doe is here! ``` *For information about operator precedence, see[Flux Operators – Operator precedence](/flux/v0/spec/operators/#operator-precedence).* ## Predicate expressions A predicate expression compares values using [comparison operators](/flux/v0/spec/operators/#comparison-operators), [logical operators](/flux/v0/spec/operators/#logical-operators), or both, and evaluates as `true` or `false`. For example: ``` "John" == "John" // Returns true 41 < 30 // Returns false "John" == "John" and 41 < 30 // Returns false "John" == "John" or 41 < 30 // Returns true ``` Flux uses predicate expressions when [filtering data](/flux/v0/get-started/query-basics/#filter)or in [conditional expressions](/flux/v0/spec/expressions/#conditional-expressions). ## Variables Assign an expression to a variable using the[assignment operator (`=`)](/flux/v0/spec/operators/#assignment-operators). Use the name (identifier) of a variable to return its value: ``` s = "foo" // string i = 1 // integer f = 2.0 // float (floating point number) s // Returns foo i // Returns 1 f // Returns 2.0 ``` Variables can be assigned to any [Flux data type](/flux/v0/data-types/). ## Data types Flux supports many data types grouped into the following categories: * [Basic types](#basic-types) * [Composite types](#composite-types) * [Regular expression types](#regular-expression-types) ### Basic types The following basic types can be represented with literal values: * [Boolean](/flux/v0/data-types/basic/bool/) * [Duration](/flux/v0/data-types/basic/duration/) * [String](/flux/v0/data-types/basic/string/) * [Time](/flux/v0/data-types/basic/time/) * [Float](/flux/v0/data-types/basic/float/) * [Integer](/flux/v0/data-types/basic/int/) ```js // Boolean true // Duration 23h4m5s // String "foo" // Time 2021-01-01T00:00:00Z // Float 1.0 // Integer 1 ``` The following basic types do not have a literal syntax, but can be created in other ways: * [Bytes](/flux/v0/data-types/basic/bytes/) * [Unsigned integers](/flux/v0/data-types/basic/uint/) * [Nulls](/flux/v0/data-types/basic/null/) ### Composite Types Flux [composite types](/flux/v0/data-types/composite/) are constructed from Flux [basic types](#basic-types). All composite types have a Flux literal representation. * [Records](#records) * [Arrays](#arrays) * [Dictionaries](#dictionaries) * [Functions](#functions) #### Records A **record** is a collections of key-value pairs. Each key is a string. Each value can be a different data type. ```js {name:"Jim", age: 42, "favorite color": "red"} ``` Use **dot notation** or **bracket notation** to access a properties of a record: > [!Note] > Use bracket notation to reference record properties with special or > white space characters in the property key. ``` o = {name:"Jim", age: 42, "favorite color": "red"} o.name // Returns Jim o.age // Returns 42 o["favorite color"] // Returns red ``` *For more information, see [Work with records](/flux/v0/data-types/composite/record/).* #### Arrays An **array** is a collection of values of the same type. ``` n = 4 l = [1,2,3,n] l // Returns [1, 2, 3, 4] ``` Use **bracket notation** to access a value at a specific index in an array: ``` a = ["foo","bar","baz","quz"] a[0] // Returns foo ``` *For more information, see [Work with arrays](/flux/v0/data-types/composite/array/).* #### Dictionaries A **dictionary** is a collection of key-value pairs with keys of the same type and values of the same type. ```js [1: "foo", 2: "bar"] ``` Use [`dict.get()`](/flux/v0/stdlib/dict/get/) to access elements in a dictionary: ``` import "dict" d = [1: "foo", 2: "bar"] dict.get(dict: d, key: "1", default: "") // Returns foo ``` *For more information, see [Work with dictionaries](/flux/v0/data-types/composite/dict/).* #### Functions A **function** is a block of code that uses a set of parameters to perform an operation. Functions can be named or anonymous. Define parameters in parentheses (`()`) and pass parameters into an operation with the [arrow operator (`=>`)](/flux/v0/spec/operators/#function-operators). ``` square = (n) => n * n square(n:3) // Returns 9 ``` > [!Note] > Flux does not support positional parameters. > Parameters must always be named when calling a function. ##### Predicate functions Predicate functions use [predicate expressions](#predicate-expressions) to evaluate input and return `true` or `false`. For example: ``` examplePredicate = (v) => v == "foo" examplePredicate(v: "foo") // Returns true examplePredicate(v: "bar") // Returns false ``` For more information about working with functions, see: * [Work with functions](/flux/v0/data-types/composite/function/) * [Define custom functions](/flux/v0/define-functions/) ### Regular expression types A **regular expression** is a regular expression pattern used to evaluate strings. Use regular expressions in [predicate expressions](#predicate-expressions) or with the [`regexp` package](/flux/v0/stdlib/regexp/). ``` regex = /^foo/ "foo" =~ regex // Returns true "bar" =~ regex // Returns false ``` ### View the string representation of any Flux type Use [`display()`](/flux/v0/stdlib/universe/display) to output the Flux literal representation of any value as a string. ``` x = bytes(v: "foo") display(v: x) // Returns "0x666f6f" ``` ## Packages The [Flux standard library](/flux/v0/stdlib/) is organized into [packages](/flux/v0/spec/packages/)that contain functions and package-specific options. The [universe package](/flux/v0/stdlib/universe/) is loaded by default. To load other packages, include an import statement for each package at the beginning of your Flux script. ```js import "array" import "math" import "influxdata/influxdb/sample" ``` ## Examples of basic syntax After reading the sections above, you can begin to apply these basic principles in real-world use cases such as creating data stream variables, custom functions, and more. * [Define data stream variables](#define-data-stream-variables) * [Define custom functions](#define-custom-functions) ### Define data stream variables A common use case for variable assignments in Flux is creating variables for one or more input data streams. The following example uses [`sample.data()`](/flux/v0/stdlib/influxdata/influxdb/sample/data/)to query sample air sensor data and assigns different streams of data to unique variables. ```js import "influxdata/influxdb/sample" data = sample.data(set: "airSensor") |> range(start: -15m) |> filter(fn: (r) => r._measurement == "airSensors") temperature = data |> filter(fn: (r) => r._field == "temperature") humidity = data |> filter(fn: (r) => r._field == "humidity") ``` These variables can be used in other functions, such as `join()`, while keeping the syntax minimal and flexible. ### Define custom functions Create a function that returns the `N` number rows with the highest values in the `_value` column. Pass the input stream (`<-`) and the number of results to return (`n`) into a custom function. Use [`sort()`](/flux/v0/stdlib/universe/sort/) and [`limit()`](/flux/v0/stdlib/universe/limit/)to find the top `n` results in the data set. ```js topN = (tables=<-, n) => tables |> sort(desc: true) |> limit(n: n) ``` Use the custom function `topN` and the `humidity` data stream variable defined above to return the top three data points in each input table. ```js humidity |> topN(n:3) ``` *For more information about creating custom functions, see [Define custom functions](/flux/v0/define-functions).* [Flux data model](/flux/v0/get-started/data-model/)[Flux query basics](/flux/v0/get-started/query-basics/) --- # Flux versions in InfluxDB Source: https://docs.influxdata.com/flux/v0/influxdb-versions/ View which versions of Flux are packaged with each version of InfluxDB. * [InfluxDB Cloud](#influxdb-cloud) * [InfluxDB Open Source (OSS)](#influxdb-open-source-oss) * [InfluxDB Enterprise](#influxdb-enterprise) ### InfluxDB Cloud |InfluxDB version|Flux version| |----------------|------------| | InfluxDB Cloud | 0.194.3 | ### InfluxDB Open Source (OSS) |InfluxDB OSS version|Flux version| |--------------------|------------| | InfluxDB 1.11 | 0.196.1 | | InfluxDB 1.7 | 0.50.2 | | InfluxDB 1.8 | 0.65.1 | | InfluxDB 2.0 | 0.131.0 | | InfluxDB 2.1 | 0.139.0 | | InfluxDB 2.2 | 0.162.0 | | InfluxDB 2.3 | 0.171.0 | | InfluxDB 2.4 | 0.179.0 | | InfluxDB 2.5 | 0.188.1 | | InfluxDB 2.6 | 0.191.0 | | InfluxDB 2.7 | 0.196.1 | | InfluxDB nightly | 0.201.0 | ### InfluxDB Enterprise |InfluxDB Enterprise version|Flux version| |---------------------------|------------| | InfluxDB Enterprise 1.7 | 0.50.2 | | InfluxDB Enterprise 1.8 | 0.65.1 | | InfluxDB Enterprise 1.9 | 0.161.0 | | InfluxDB Enterprise 1.10 | 0.196.1 | | InfluxDB Enterprise 1.11 | 0.196.1 | | InfluxDB version | Flux version | | --- | --- | | InfluxDB version | Flux version | | InfluxDB Cloud | 0.194.3 | | InfluxDB OSS version | Flux version | | --- | --- | | InfluxDB OSS version | Flux version | | InfluxDB 1.11 | 0.196.1 | | InfluxDB 1.7 | 0.50.2 | | InfluxDB 1.8 | 0.65.1 | | InfluxDB 2.0 | 0.131.0 | | InfluxDB 2.1 | 0.139.0 | | InfluxDB 2.2 | 0.162.0 | | InfluxDB 2.3 | 0.171.0 | | InfluxDB 2.4 | 0.179.0 | | InfluxDB 2.5 | 0.188.1 | | InfluxDB 2.6 | 0.191.0 | | InfluxDB 2.7 | 0.196.1 | | InfluxDB nightly | 0.201.0 | | InfluxDB Enterprise version | Flux version | | --- | --- | | InfluxDB Enterprise version | Flux version | | InfluxDB Enterprise 1.7 | 0.50.2 | | InfluxDB Enterprise 1.8 | 0.65.1 | | InfluxDB Enterprise 1.9 | 0.161.0 | | InfluxDB Enterprise 1.10 | 0.196.1 | | InfluxDB Enterprise 1.11 | 0.196.1 | --- # Join data Source: https://docs.influxdata.com/flux/v0/join-data/ Use the Flux [`join` package](/flux/v0/stdlib/join/) to join two data sets based on common values. Learn how join two data sets using the following join methods: [ **Inner join** ](#perform-an-inner-join) [ **Left outer join** ](#perform-a-left-outer-join) [ **Right outer join** ](#perform-a-right-outer-join) [ **Full outer join** ](#perform-a-full-outer-join) > [!Note] > #### When to use the join package > > We recommend using the `join` package to join streams that have mostly different > schemas or that come from two separate data sources. > If you’re joining data from the same data source with the same schema, using[`union()`](/flux/v0/stdlib/universe/union/) and [`pivot()`](/flux/v0/stdlib/universe/pivot/)to combine the data will likely be more performant. > > For more information, see[When to use union and pivot instead of join functions](/influxdb/v2/query-data/flux/join/#when-to-use-union-and-pivot-instead-of-join-functions). * [How join functions work](#how-join-functions-work) * [Input streams](#input-streams) * [Join predicate function (on)](#join-predicate-function-on) * [Join output function (as)](#join-output-function-as) * [Perform join operations](#perform-join-operations) * [Perform an inner join](#perform-an-inner-join) * [Perform a left outer join](#perform-a-left-outer-join) * [Perform a right outer join](#perform-a-right-outer-join) * [Perform a full outer join](#perform-a-full-outer-join) * [Join on time](#join-on-time) * [Troubleshoot join operations](#troubleshoot-join-operations) ## How join functions work `join` functions join *two* streams of tables together based on common values in each input stream. * [Input streams](#input-streams) * [Join predicate function (on)](#join-predicate-function-on) * [Join output function (as)](#join-output-function-as) ### Input streams Each input stream is assigned to the `left` or `right` parameter. Input streams can be defined from any valid data source. For more information, see: * [Query data sources](/flux/v0/query-data/) * Define ad hoc tables with [`array.from()`](/flux/v0/stdlib/array/from/) #### Data requirements To join data, each input stream must have the following: * **One or more columns with common values to join on**. Columns do not need identical labels, but they do need to have comparable values. * **Identical [group keys](/flux/v0/get-started/data-model/#group-key)**. Functions in the `join` package use group keys to quickly determine what tables from each input stream should be paired and evaluated for the join operation. *Both input streams should have the same group key.*If they don’t, your join operation may not find any matching tables and will return unexpected output. If the group keys of your input streams are not identical, use[`group()`](/flux/v0/stdlib/universe/group/) to regroup each input stream before joining them together. > [!Note] > Only tables with the same [group key instance](/flux/v0/get-started/data-model/#example-group-key-instances)are joined. ### Join predicate function (on) `join` package functions require the `on` parameter to compare values from each input stream (represented by `l` (left) and `r` (right)) and returns `true` or `false`. Rows that return `true` are joined. This parameter is a [predicate function](/flux/v0/get-started/syntax-basics/#predicate-functions). ```js (l, r) => l.column == r.column ``` ### Join output function (as) `join` package functions *(except [`join.time()`](/flux/v0/stdlib/join/time/))*require the `as` parameter to define the output schema of the join. The `as` parameter returns a new record using values from joined rows–left (`l`) and right (`r`). ```js (l, r) => ({l with name: r.name, location: r.location}) ``` > [!Note] > #### Do not modify group key columns > > Do not modify group key columns. The `as` function must return the same group key as both input streams to successfully perform a join. ## Perform join operations The `join` package supports the following join types and special use cases: * [Perform an inner join](#perform-an-inner-join) * [Perform a left outer join](#perform-a-left-outer-join) * [Perform a right outer join](#perform-a-right-outer-join) * [Perform a full outer join](#perform-a-full-outer-join) * [Join on time](#join-on-time) ### [Perform an inner join](/flux/v0/join-data/inner/) Use [`join.inner()`](/flux/v0/stdlib/join/inner/) to perform an inner join of two streams of data. Inner joins drop any rows from both input streams that do not have a matching row in the other stream. ```js import "join" left = from(bucket: "example-bucket-1") |> //... right = from(bucket: "example-bucket-2") |> //... join.inner( left: left, right: right, on: (l, r) => l.column == r.column, as: (l, r) => ({l with name: r.name, location: r.location}), ) ``` [Read more ](/flux/v0/join-data/inner/) ### [Perform a left outer join](/flux/v0/join-data/left-outer/) Use [`join.left()`](/flux/v0/stdlib/join/left/) to perform an outer left join of two streams of data. Left joins output a row for each row in the **left** data stream with data matching from the **right** data stream. If there is no matching data in the **right** data stream, non-group-key columns with values from the **right** data stream are *null*. ```js import "join" left = from(bucket: "example-bucket-1") |> //... right = from(bucket: "example-bucket-2") |> //... join.left( left: left, right: right, on: (l, r) => l.column == r.column, as: (l, r) => ({l with name: r.name, location: r.location}), ) ``` [Read more ](/flux/v0/join-data/left-outer/) ### [Perform a right outer join](/flux/v0/join-data/right-outer/) Use [`join.right()`](/flux/v0/stdlib/join/right/) to perform an right outer join of two streams of data. Right joins output a row for each row in the **right** data stream with data matching from the **left** data stream. If there is no matching data in the **left** data stream, non-group-key columns with values from the **left** data stream are *null*. ```js import "join" left = from(bucket: "example-bucket-1") |> //... right = from(bucket: "example-bucket-2") |> //... join.right( left: left, right: right, on: (l, r) => l.column == r.column, as: (l, r) => ({r with name: l.name, location: l.location}), ) ``` [Read more ](/flux/v0/join-data/right-outer/) ### [Perform a full outer join](/flux/v0/join-data/full-outer/) Use [`join.full()`](/flux/v0/stdlib/join/full/) to perform an full outer join of two streams of data. Full outer joins output a row for all rows in both the **left** and **right** input streams and join rows that match according to the `on` predicate. ``` import "join" left = from(bucket: "example-bucket-1") |> //... right = from(bucket: "example-bucket-2") |> //... join.full( left: left, right: right, on: (l, r) => l.id== r.id, as: (l, r) => { id = if exists l.id then l.id else r.id return {name: l.name, location: r.location, id: id} }, ) ``` [Read more ](/flux/v0/join-data/full-outer/) ### [Join on time](/flux/v0/join-data/time/) Use [`join.time()`](/flux/v0/stdlib/join/time/) to join two streams of data based on time values in the `_time` column. This type of join operation is common when joining two streams of [time series data](/influxdb/v2/reference/glossary/#time-series-data). ```js import "join" left = from(bucket: "example-bucket-1") |> //... right = from(bucket: "example-bucket-2") |> //... join.time( left: left, right: right, as: (l, r) => ({l with field1: l._value, field2: r._value_}), ) ``` [Read more ](/flux/v0/join-data/time/) ## Troubleshoot join operations For information about unexpected behaviors and errors when using the `join` package, see [Troubleshoot join operations](/flux/v0/join-data/troubleshoot-joins/). #### Related * [join package](/flux/v0/stdlib/join/) * [join.inner() function](/flux/v0/stdlib/join/inner/) * [join.left() function](/flux/v0/stdlib/join/left/) * [join.right() function](/flux/v0/stdlib/join/right/) * [join.full() function](/flux/v0/stdlib/join/full/) * [join.time() function](/flux/v0/stdlib/join/time/) --- # Perform a full outer join Source: https://docs.influxdata.com/flux/v0/join-data/full-outer/ Use [`join.full()`](/flux/v0/stdlib/join/full/) to perform an full outer join of two streams of data. Full outer joins output a row for all rows in both the **left** and **right** input streams and join rows that match according to the `on` predicate. [](#view-table-illustration-of-a-full-outer-join) View table illustration of a full outer join #### left | | | | |---|---|---| |r1 | ● | ● | |r2 | ● | ● | #### right | | | | |---|---|---| |r1 | ▲ | ▲ | |r3 | ▲ | ▲ | |r4 | ▲ | ▲ | #### Full outer join result | | | | | | |---|---|---|---|---| |r1 | ● | ● | ▲ | ▲ | |r2 | ● | ● | | | |r3 | | | ▲ | ▲ | |r4 | | | ▲ | ▲ | ## Use join.full to join your data 1. Import the `join` package. 2. Define the **left** and **right** data streams to join: * Each stream must have one or more columns with common values. Column labels do not need to match, but column values do. * Each stream should have identical [group keys](/flux/v0/get-started/data-model/#group-key). *For more information, see [join data requirements](/flux/v0/join-data/#data-requirements).* 3. Use `join.full()` to join the two streams together. Provide the following required parameters: * `left`: Stream of data representing the left side of the join. * `right`: Stream of data representing the right side of the join. * `on`: [Join predicate](/flux/v0/join-data/#join-predicate-function-on). For example: `(l, r) => l.column == r.column`. * `as`: [Join output function](/flux/v0/join-data/#join-output-function-as)that returns a record with values from each input stream. ##### Account for missing, non-group-key values ##### In a full outer join, it’s possible for either the left (`l`) or right (`r`) to contain *null* values for the columns used in the join operation and default to a default record (group key columns are populated and other columns are *null*).`l` and `r` will never both use default records at the same time. To ensure non-null values are included in the output for non-group-key columns, check for the existence of a value in the `l` or `r` record, and return the value that exists: ``` (l, r) => { id = if exists l.id then l.id else r.id return {_time: l.time, location: r.location, id: id} } ``` The following example uses a filtered selection from the[**machineProduction** sample data set](/flux/v0/stdlib/influxdata/influxdb/sample/data/#set)as the **left** data stream and an ad-hoc table created with [`array.from()`](/flux/v0/stdlib/array/from/)as the **right** data stream. > [!Note] > #### Example data grouping > > The example below ungroups the **left** stream to match the grouping of the **right** stream. > After the two streams are joined together, the joined data is grouped by `stationID`and sorted by `_time`. ```js import "array" import "influxdata/influxdb/sample" import "join" left = sample.data(set: "machineProduction") |> filter(fn: (r) => r.stationID == "g1" or r.stationID == "g2" or r.stationID == "g3") |> filter(fn: (r) => r._field == "oil_temp") |> limit(n: 5) right = array.from( rows: [ {station: "g1", opType: "auto", last_maintained: 2021-07-15T00:00:00Z}, {station: "g2", opType: "manned", last_maintained: 2021-07-02T00:00:00Z}, {station: "g4", opType: "auto", last_maintained: 2021-08-04T00:00:00Z}, ], ) join.full( left: left |> group(), right: right, on: (l, r) => l.stationID == r.station, as: (l, r) => { stationID = if exists l.stationID then l.stationID else r.station return { stationID: stationID, _time: l._time, _field: l._field, _value: l._value, opType: r.opType, maintained: r.last_maintained, } }, ) |> group(columns: ["stationID"]) |> sort(columns: ["_time"]) ``` [](#view-example-input-and-output-data) View example input and output data ### Input #### left > [!Note] > *`_start` and `_stop` columns have been omitted.* | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g1 |oil\_temp| 39.1 | |2021-08-01T00:00:11.51Z| machinery | g1 |oil\_temp| 40.3 | |2021-08-01T00:00:19.53Z| machinery | g1 |oil\_temp| 40.6 | |2021-08-01T00:00:25.1Z | machinery | g1 |oil\_temp| 40.72 | |2021-08-01T00:00:36.88Z| machinery | g1 |oil\_temp| 40.8 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:00:27.93Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:00:54.96Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:01:17.27Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:01:41.84Z| machinery | g2 |oil\_temp| 40.6 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:14.46Z| machinery | g3 |oil\_temp| 41.36 | |2021-08-01T00:00:25.29Z| machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:38.77Z| machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:51.2Z | machinery | g3 |oil\_temp| 41.4 | #### right |station|opType| last\_maintained | |-------|------|--------------------| | g1 | auto |2021-07-15T00:00:00Z| | g2 |manned|2021-07-02T00:00:00Z| | g4 | auto |2021-08-04T00:00:00Z| ### Output | \_time |stationID| \_field |\_value| maintained |opType| |-----------------------|---------|---------|-------|--------------------|------| | 2021-08-01T00:00:00Z | g1 |oil\_temp| 39.1 |2021-07-15T00:00:00Z| auto | |2021-08-01T00:00:11.51Z| g1 |oil\_temp| 40.3 |2021-07-15T00:00:00Z| auto | |2021-08-01T00:00:19.53Z| g1 |oil\_temp| 40.6 |2021-07-15T00:00:00Z| auto | |2021-08-01T00:00:25.1Z | g1 |oil\_temp| 40.72 |2021-07-15T00:00:00Z| auto | |2021-08-01T00:00:36.88Z| g1 |oil\_temp| 40.8 |2021-07-15T00:00:00Z| auto | | \_time |stationID| \_field |\_value| maintained |opType| |-----------------------|---------|---------|-------|--------------------|------| | 2021-08-01T00:00:00Z | g2 |oil\_temp| 40.6 |2021-07-02T00:00:00Z|manned| |2021-08-01T00:00:27.93Z| g2 |oil\_temp| 40.6 |2021-07-02T00:00:00Z|manned| |2021-08-01T00:00:54.96Z| g2 |oil\_temp| 40.6 |2021-07-02T00:00:00Z|manned| |2021-08-01T00:01:17.27Z| g2 |oil\_temp| 40.6 |2021-07-02T00:00:00Z|manned| |2021-08-01T00:01:41.84Z| g2 |oil\_temp| 40.6 |2021-07-02T00:00:00Z|manned| | \_time |stationID| \_field |\_value|maintained|opType| |-----------------------|---------|---------|-------|----------|------| | 2021-08-01T00:00:00Z | g3 |oil\_temp| 41.4 | | | |2021-08-01T00:00:14.46Z| g3 |oil\_temp| 41.36 | | | |2021-08-01T00:00:25.29Z| g3 |oil\_temp| 41.4 | | | |2021-08-01T00:00:38.77Z| g3 |oil\_temp| 41.4 | | | |2021-08-01T00:00:51.2Z | g3 |oil\_temp| 41.4 | | | |\_time|stationID|\_field|\_value| maintained |opType| |------|---------|-------|-------|--------------------|------| | | g4 | | |2021-08-04T00:00:00Z| auto | #### Things to note about the join output * Because the [right stream](#right-input) does not have rows with the `g3` stationID tag, the joined output includes rows with the `g3` stationID tag from the [left stream](#left-input)with *null* values in columns populated from the **right** stream. * Because the [left stream](#left-input) does not have rows with the `g4` stationID tag, the joined output includes rows with the `g4` stationID tag from the [right stream](#right-input)with *null* values in columns populated from the **left** stream. #### Related * [Troubleshoot join operations](/flux/v0/join-data/troubleshoot-joins/) * [join package](/flux/v0/stdlib/join/) * [join.full() function](/flux/v0/stdlib/join/full/) | | | | | --- | --- | --- | | | | | | r1 | ● | ● | | r2 | ● | ● | | | | | | --- | --- | --- | | | | | | r1 | ▲ | ▲ | | r3 | ▲ | ▲ | | r4 | ▲ | ▲ | | | | | | | | --- | --- | --- | --- | --- | | | | | | | | r1 | ● | ● | ▲ | ▲ | | r2 | ● | ● | | | | r3 | | | ▲ | ▲ | | r4 | | | ▲ | ▲ | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g1 | oil_temp | 39.1 | | 2021-08-01T00:00:11.51Z | machinery | g1 | oil_temp | 40.3 | | 2021-08-01T00:00:19.53Z | machinery | g1 | oil_temp | 40.6 | | 2021-08-01T00:00:25.1Z | machinery | g1 | oil_temp | 40.72 | | 2021-08-01T00:00:36.88Z | machinery | g1 | oil_temp | 40.8 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:00:27.93Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:00:54.96Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:01:17.27Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:01:41.84Z | machinery | g2 | oil_temp | 40.6 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:14.46Z | machinery | g3 | oil_temp | 41.36 | | 2021-08-01T00:00:25.29Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:38.77Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:51.2Z | machinery | g3 | oil_temp | 41.4 | | station | opType | last_maintained | | --- | --- | --- | | station | opType | last_maintained | | g1 | auto | 2021-07-15T00:00:00Z | | g2 | manned | 2021-07-02T00:00:00Z | | g4 | auto | 2021-08-04T00:00:00Z | | _time | stationID | _field | _value | maintained | opType | | --- | --- | --- | --- | --- | --- | | _time | stationID | _field | _value | maintained | opType | | 2021-08-01T00:00:00Z | g1 | oil_temp | 39.1 | 2021-07-15T00:00:00Z | auto | | 2021-08-01T00:00:11.51Z | g1 | oil_temp | 40.3 | 2021-07-15T00:00:00Z | auto | | 2021-08-01T00:00:19.53Z | g1 | oil_temp | 40.6 | 2021-07-15T00:00:00Z | auto | | 2021-08-01T00:00:25.1Z | g1 | oil_temp | 40.72 | 2021-07-15T00:00:00Z | auto | | 2021-08-01T00:00:36.88Z | g1 | oil_temp | 40.8 | 2021-07-15T00:00:00Z | auto | | _time | stationID | _field | _value | maintained | opType | | --- | --- | --- | --- | --- | --- | | _time | stationID | _field | _value | maintained | opType | | 2021-08-01T00:00:00Z | g2 | oil_temp | 40.6 | 2021-07-02T00:00:00Z | manned | | 2021-08-01T00:00:27.93Z | g2 | oil_temp | 40.6 | 2021-07-02T00:00:00Z | manned | | 2021-08-01T00:00:54.96Z | g2 | oil_temp | 40.6 | 2021-07-02T00:00:00Z | manned | | 2021-08-01T00:01:17.27Z | g2 | oil_temp | 40.6 | 2021-07-02T00:00:00Z | manned | | 2021-08-01T00:01:41.84Z | g2 | oil_temp | 40.6 | 2021-07-02T00:00:00Z | manned | | _time | stationID | _field | _value | maintained | opType | | --- | --- | --- | --- | --- | --- | | _time | stationID | _field | _value | maintained | opType | | 2021-08-01T00:00:00Z | g3 | oil_temp | 41.4 | | | | 2021-08-01T00:00:14.46Z | g3 | oil_temp | 41.36 | | | | 2021-08-01T00:00:25.29Z | g3 | oil_temp | 41.4 | | | | 2021-08-01T00:00:38.77Z | g3 | oil_temp | 41.4 | | | | 2021-08-01T00:00:51.2Z | g3 | oil_temp | 41.4 | | | | _time | stationID | _field | _value | maintained | opType | | --- | --- | --- | --- | --- | --- | | _time | stationID | _field | _value | maintained | opType | | | g4 | | | 2021-08-04T00:00:00Z | auto | --- # Perform an inner join Source: https://docs.influxdata.com/flux/v0/join-data/inner/ Use [`join.inner()`](/flux/v0/stdlib/join/inner/) to perform an inner join of two streams of data. Inner joins drop any rows from both input streams that do not have a matching row in the other stream. [](#view-table-illustration-of-an-inner-join) View table illustration of an inner join #### left | | | | |---|---|---| |r1 | ● | ● | |r2 | ● | ● | #### right | | | | |---|---|---| |r1 | ▲ | ▲ | |r3 | ▲ | ▲ | |r4 | ▲ | ▲ | #### Inner join result | | | | | | |---|---|---|---|---| |r1 | ● | ● | ▲ | ▲ | ## Use join.inner to join your data 1. Import the `join` package. 2. Define the **left** and **right** data streams to join: * Each stream must have one or more columns with common values. Column labels do not need to match, but column values do. * Each stream should have identical [group keys](/flux/v0/get-started/data-model/#group-key). *For more information, see [join data requirements](/flux/v0/join-data/#data-requirements).* 3. Use `join.inner()` to join the two streams together. Provide the following required parameters: * `left`: Stream of data representing the left side of the join. * `right`: Stream of data representing the right side of the join. * `on`: [Join predicate](/flux/v0/join-data/#join-predicate-function-on). For example: `(l, r) => l.column == r.column`. * `as`: [Join output function](/flux/v0/join-data/#join-output-function-as)that returns a record with values from each input stream. For example: `(l, r) => ({l with column1: r.column1, column2: r.column2})`. The following example uses a filtered selection from the[**machineProduction** sample data set](/flux/v0/stdlib/influxdata/influxdb/sample/data/#set)as the **left** data stream and an ad-hoc table created with [`array.from()`](/flux/v0/stdlib/array/from/)as the **right** data stream. > [!Note] > #### Example data grouping > > The example below ungroups the **left** stream to match the grouping of the **right** stream. > After the two streams are joined together, the joined data is grouped by `stationID`. ```js import "array" import "influxdata/influxdb/sample" import "join" left = sample.data(set: "machineProduction") |> filter(fn: (r) => r.stationID == "g1" or r.stationID == "g2" or r.stationID == "g3") |> filter(fn: (r) => r._field == "oil_temp") |> limit(n: 5) right = array.from( rows: [ {station: "g1", opType: "auto", last_maintained: 2021-07-15T00:00:00Z}, {station: "g2", opType: "manned", last_maintained: 2021-07-02T00:00:00Z}, ], ) join.inner( left: left |> group(), right: right, on: (l, r) => l.stationID == r.station, as: (l, r) => ({l with opType: r.opType, maintained: r.last_maintained}), ) |> group(columns: ["stationID"]) ``` [](#view-example-input-and-output-data) View example input and output data > [!Note] > *`_start` and `_stop` columns have been omitted from example input and output.* ### Input #### left | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g1 |oil\_temp| 39.1 | |2021-08-01T00:00:11.51Z| machinery | g1 |oil\_temp| 40.3 | |2021-08-01T00:00:19.53Z| machinery | g1 |oil\_temp| 40.6 | |2021-08-01T00:00:25.1Z | machinery | g1 |oil\_temp| 40.72 | |2021-08-01T00:00:36.88Z| machinery | g1 |oil\_temp| 40.8 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:00:27.93Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:00:54.96Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:01:17.27Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:01:41.84Z| machinery | g2 |oil\_temp| 40.6 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:14.46Z| machinery | g3 |oil\_temp| 41.36 | |2021-08-01T00:00:25.29Z| machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:38.77Z| machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:51.2Z | machinery | g3 |oil\_temp| 41.4 | #### right |station|opType| last\_maintained | |-------|------|--------------------| | g1 | auto |2021-07-15T00:00:00Z| | g2 |manned|2021-07-02T00:00:00Z| ### Output | \_time |\_measurement|stationID| \_field |\_value|opType| maintained | |-----------------------|-------------|---------|---------|-------|------|--------------------| | 2021-08-01T00:00:00Z | machinery | g1 |oil\_temp| 39.1 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:11.51Z| machinery | g1 |oil\_temp| 40.3 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:19.53Z| machinery | g1 |oil\_temp| 40.6 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:25.1Z | machinery | g1 |oil\_temp| 40.72 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:36.88Z| machinery | g1 |oil\_temp| 40.8 | auto |2021-07-15T00:00:00Z| | \_time |\_measurement|stationID| \_field |\_value|opType| maintained | |-----------------------|-------------|---------|---------|-------|------|--------------------| | 2021-08-01T00:00:00Z | machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:00:27.93Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:00:54.96Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:01:17.27Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:01:41.84Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| #### Things to note about the join output * Because the [right stream](#right-input) does not have a row with the `g3` station tag, the joined output drops all rows with the `g3` stationID tag from the [left stream](#left-input).`join.inner()` drops any rows that do not have a matching row in the other data stream. #### Related * [Troubleshoot join operations](/flux/v0/join-data/troubleshoot-joins/) * [join package](/flux/v0/stdlib/join/) * [join.inner() function](/flux/v0/stdlib/join/inner/) | | | | | --- | --- | --- | | | | | | r1 | ● | ● | | r2 | ● | ● | | | | | | --- | --- | --- | | | | | | r1 | ▲ | ▲ | | r3 | ▲ | ▲ | | r4 | ▲ | ▲ | | | | | | | | --- | --- | --- | --- | --- | | | | | | | | r1 | ● | ● | ▲ | ▲ | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g1 | oil_temp | 39.1 | | 2021-08-01T00:00:11.51Z | machinery | g1 | oil_temp | 40.3 | | 2021-08-01T00:00:19.53Z | machinery | g1 | oil_temp | 40.6 | | 2021-08-01T00:00:25.1Z | machinery | g1 | oil_temp | 40.72 | | 2021-08-01T00:00:36.88Z | machinery | g1 | oil_temp | 40.8 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:00:27.93Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:00:54.96Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:01:17.27Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:01:41.84Z | machinery | g2 | oil_temp | 40.6 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:14.46Z | machinery | g3 | oil_temp | 41.36 | | 2021-08-01T00:00:25.29Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:38.77Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:51.2Z | machinery | g3 | oil_temp | 41.4 | | station | opType | last_maintained | | --- | --- | --- | | station | opType | last_maintained | | g1 | auto | 2021-07-15T00:00:00Z | | g2 | manned | 2021-07-02T00:00:00Z | | _time | _measurement | stationID | _field | _value | opType | maintained | | --- | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | opType | maintained | | 2021-08-01T00:00:00Z | machinery | g1 | oil_temp | 39.1 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:11.51Z | machinery | g1 | oil_temp | 40.3 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:19.53Z | machinery | g1 | oil_temp | 40.6 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:25.1Z | machinery | g1 | oil_temp | 40.72 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:36.88Z | machinery | g1 | oil_temp | 40.8 | auto | 2021-07-15T00:00:00Z | | _time | _measurement | stationID | _field | _value | opType | maintained | | --- | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | opType | maintained | | 2021-08-01T00:00:00Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:00:27.93Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:00:54.96Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:01:17.27Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:01:41.84Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | --- # Perform a left outer join Source: https://docs.influxdata.com/flux/v0/join-data/left-outer/ Use [`join.left()`](/flux/v0/stdlib/join/left/) to perform an left outer join of two streams of data. Left joins output a row for each row in the **left** data stream with data matching from the **right** data stream. If there is no matching data in the **right**data stream, non-group-key columns with values from the **right** data stream are *null*. [](#view-table-illustration-of-a-left-outer-join) View table illustration of a left outer join #### left | | | | |---|---|---| |r1 | ● | ● | |r2 | ● | ● | #### right | | | | |---|---|---| |r1 | ▲ | ▲ | |r3 | ▲ | ▲ | |r4 | ▲ | ▲ | #### Left outer join result | | | | | | |---|---|---|---|---| |r1 | ● | ● | ▲ | ▲ | |r2 | ● | ● | | | ## Use join.left to join your data 1. Import the `join` package. 2. Define the **left** and **right** data streams to join: * Each stream must have one or more columns with common values. Column labels do not need to match, but column values do. * Each stream should have identical [group keys](/flux/v0/get-started/data-model/#group-key). *For more information, see [join data requirements](/flux/v0/join-data/#data-requirements).* 3. Use `join.left()` to join the two streams together. Provide the following parameters: * `left`: Stream of data representing the left side of the join. * `right`: Stream of data representing the right side of the join. * `on`: [Join predicate](/flux/v0/join-data/#join-predicate-function-on). For example: `(l, r) => l.column == r.column`. * `as`: [Join output function](/flux/v0/join-data/#join-output-function-as)that returns a record with values from each input stream. For example: `(l, r) => ({l with column1: r.column1, column2: r.column2})`. The following example uses a filtered selection from the[**machineProduction** sample data set](/flux/v0/stdlib/influxdata/influxdb/sample/data/#set)as the **left** data stream and an ad-hoc table created with [`array.from()`](/flux/v0/stdlib/array/from/)as the **right** data stream. > [!Note] > #### Example data grouping > > The example below ungroups the **left** stream to match the grouping of the **right** stream. > After the two streams are joined together, the joined data is grouped by `stationID`. ```js import "array" import "influxdata/influxdb/sample" import "join" left = sample.data(set: "machineProduction") |> filter(fn: (r) => r.stationID == "g1" or r.stationID == "g2" or r.stationID == "g3") |> filter(fn: (r) => r._field == "oil_temp") |> limit(n: 5) right = array.from( rows: [ {station: "g1", opType: "auto", last_maintained: 2021-07-15T00:00:00Z}, {station: "g2", opType: "manned", last_maintained: 2021-07-02T00:00:00Z}, ], ) join.left( left: left |> group(), right: right, on: (l, r) => l.stationID == r.station, as: (l, r) => ({l with opType: r.opType, maintained: r.last_maintained}), ) |> group(columns: ["stationID"]) ``` [](#view-example-input-and-output-data) View example input and output data > [!Note] > *`_start` and `_stop` columns have been omitted from example input and output.* ### Input #### left | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g1 |oil\_temp| 39.1 | |2021-08-01T00:00:11.51Z| machinery | g1 |oil\_temp| 40.3 | |2021-08-01T00:00:19.53Z| machinery | g1 |oil\_temp| 40.6 | |2021-08-01T00:00:25.1Z | machinery | g1 |oil\_temp| 40.72 | |2021-08-01T00:00:36.88Z| machinery | g1 |oil\_temp| 40.8 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:00:27.93Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:00:54.96Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:01:17.27Z| machinery | g2 |oil\_temp| 40.6 | |2021-08-01T00:01:41.84Z| machinery | g2 |oil\_temp| 40.6 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| | 2021-08-01T00:00:00Z | machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:14.46Z| machinery | g3 |oil\_temp| 41.36 | |2021-08-01T00:00:25.29Z| machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:38.77Z| machinery | g3 |oil\_temp| 41.4 | |2021-08-01T00:00:51.2Z | machinery | g3 |oil\_temp| 41.4 | #### right |station|opType| last\_maintained | |-------|------|--------------------| | g1 | auto |2021-07-15T00:00:00Z| | g2 |manned|2021-07-02T00:00:00Z| ### Output | \_time |\_measurement|stationID| \_field |\_value|opType| maintained | |-----------------------|-------------|---------|---------|-------|------|--------------------| | 2021-08-01T00:00:00Z | machinery | g1 |oil\_temp| 39.1 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:11.51Z| machinery | g1 |oil\_temp| 40.3 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:19.53Z| machinery | g1 |oil\_temp| 40.6 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:25.1Z | machinery | g1 |oil\_temp| 40.72 | auto |2021-07-15T00:00:00Z| |2021-08-01T00:00:36.88Z| machinery | g1 |oil\_temp| 40.8 | auto |2021-07-15T00:00:00Z| | \_time |\_measurement|stationID| \_field |\_value|opType| maintained | |-----------------------|-------------|---------|---------|-------|------|--------------------| | 2021-08-01T00:00:00Z | machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:00:27.93Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:00:54.96Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:01:17.27Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| |2021-08-01T00:01:41.84Z| machinery | g2 |oil\_temp| 40.6 |manned|2021-07-02T00:00:00Z| | \_time |\_measurement|stationID| \_field |\_value|opType|maintained| |-----------------------|-------------|---------|---------|-------|------|----------| | 2021-08-01T00:00:00Z | machinery | g3 |oil\_temp| 41.4 | | | |2021-08-01T00:00:14.46Z| machinery | g3 |oil\_temp| 41.3 | | | |2021-08-01T00:00:25.29Z| machinery | g3 |oil\_temp| 41.4 | | | |2021-08-01T00:00:38.77Z| machinery | g3 |oil\_temp| 41.4 | | | |2021-08-01T00:00:51.2Z | machinery | g3 |oil\_temp| 41.4 | | | #### Things to note about the join output * Because the [right stream](#right-input) does not have a row with the `g3` station tag, rows from the [left stream](#left-input) with the `g3` stationID tag include*null* values in columns that are populated from the right stream (`r`) in the`as` parameter. #### Related * [Troubleshoot join operations](/flux/v0/join-data/troubleshoot-joins/) * [join package](/flux/v0/stdlib/join/) * [join.left() function](/flux/v0/stdlib/join/left/) | | | | | --- | --- | --- | | | | | | r1 | ● | ● | | r2 | ● | ● | | | | | | --- | --- | --- | | | | | | r1 | ▲ | ▲ | | r3 | ▲ | ▲ | | r4 | ▲ | ▲ | | | | | | | | --- | --- | --- | --- | --- | | | | | | | | r1 | ● | ● | ▲ | ▲ | | r2 | ● | ● | | | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g1 | oil_temp | 39.1 | | 2021-08-01T00:00:11.51Z | machinery | g1 | oil_temp | 40.3 | | 2021-08-01T00:00:19.53Z | machinery | g1 | oil_temp | 40.6 | | 2021-08-01T00:00:25.1Z | machinery | g1 | oil_temp | 40.72 | | 2021-08-01T00:00:36.88Z | machinery | g1 | oil_temp | 40.8 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:00:27.93Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:00:54.96Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:01:17.27Z | machinery | g2 | oil_temp | 40.6 | | 2021-08-01T00:01:41.84Z | machinery | g2 | oil_temp | 40.6 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:14.46Z | machinery | g3 | oil_temp | 41.36 | | 2021-08-01T00:00:25.29Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:38.77Z | machinery | g3 | oil_temp | 41.4 | | 2021-08-01T00:00:51.2Z | machinery | g3 | oil_temp | 41.4 | | station | opType | last_maintained | | --- | --- | --- | | station | opType | last_maintained | | g1 | auto | 2021-07-15T00:00:00Z | | g2 | manned | 2021-07-02T00:00:00Z | | _time | _measurement | stationID | _field | _value | opType | maintained | | --- | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | opType | maintained | | 2021-08-01T00:00:00Z | machinery | g1 | oil_temp | 39.1 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:11.51Z | machinery | g1 | oil_temp | 40.3 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:19.53Z | machinery | g1 | oil_temp | 40.6 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:25.1Z | machinery | g1 | oil_temp | 40.72 | auto | 2021-07-15T00:00:00Z | | 2021-08-01T00:00:36.88Z | machinery | g1 | oil_temp | 40.8 | auto | 2021-07-15T00:00:00Z | | _time | _measurement | stationID | _field | _value | opType | maintained | | --- | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | opType | maintained | | 2021-08-01T00:00:00Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:00:27.93Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:00:54.96Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:01:17.27Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | 2021-08-01T00:01:41.84Z | machinery | g2 | oil_temp | 40.6 | manned | 2021-07-02T00:00:00Z | | _time | _measurement | stationID | _field | _value | opType | maintained | | --- | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | opType | maintained | | 2021-08-01T00:00:00Z | machinery | g3 | oil_temp | 41.4 | | | | 2021-08-01T00:00:14.46Z | machinery | g3 | oil_temp | 41.3 | | | | 2021-08-01T00:00:25.29Z | machinery | g3 | oil_temp | 41.4 | | | | 2021-08-01T00:00:38.77Z | machinery | g3 | oil_temp | 41.4 | | | | 2021-08-01T00:00:51.2Z | machinery | g3 | oil_temp | 41.4 | | | --- # Perform a right outer join Source: https://docs.influxdata.com/flux/v0/join-data/right-outer/ Use [`join.right()`](/flux/v0/stdlib/join/right/) to perform an right outer join of two streams of data. Right joins output a row for each row in the **right** data stream with data matching from the **left** data stream. If there is no matching data in the **left**data stream, non-group-key columns with values from the **left** data stream are *null*. [](#view-table-illustration-of-a-right-outer-join) View table illustration of a right outer join #### left | | | | |---|---|---| |r1 | ● | ● | |r2 | ● | ● | #### right | | | | |---|---|---| |r1 | ▲ | ▲ | |r3 | ▲ | ▲ | |r4 | ▲ | ▲ | #### Right outer join result | | | | | | |---|---|---|---|---| |r1 | ● | ● | ▲ | ▲ | |r3 | | | ▲ | ▲ | |r4 | | | ▲ | ▲ | ## Use join.right to join your data 1. Import the `join` package. 2. Define the **left** and **right** data streams to join: * Each stream must have one or more columns with common values. Column labels do not need to match, but column values do. * Each stream should have identical [group keys](/flux/v0/get-started/data-model/#group-key). *For more information, see [join data requirements](/flux/v0/join-data/#data-requirements).* 3. Use `join.right()` to join the two streams together. Provide the following required parameters: * `left`: Stream of data representing the left side of the join. * `right`: Stream of data representing the right side of the join. * `on`: [Join predicate](/flux/v0/join-data/#join-predicate-function-on). For example: `(l, r) => l.column == r.column`. * `as`: [Join output function](/flux/v0/join-data/#join-output-function-as)that returns a record with values from each input stream. For example: `(l, r) => ({r with column1: l.column1, column2: l.column2})`. The following example uses a filtered selection from the[**machineProduction** sample data set](/flux/v0/stdlib/influxdata/influxdb/sample/data/#set)as the **left** data stream and an ad-hoc table created with [`array.from()`](/flux/v0/stdlib/array/from/)as the **right** data stream. > [!Note] > #### Example data grouping > > The example below ungroups the **left** stream to match the grouping of the **right** stream. ```js import "array" import "influxdata/influxdb/sample" import "join" left = sample.data(set: "machineProduction") |> filter(fn: (r) => r.stationID == "g1" or r.stationID == "g2" or r.stationID == "g3") |> filter(fn: (r) => r._field == "oil_temp") |> last() right = array.from( rows: [ {station: "g1", opType: "auto", last_maintained: 2021-07-15T00:00:00Z}, {station: "g2", opType: "manned", last_maintained: 2021-07-02T00:00:00Z}, ], ) join.right( left: left |> group(), right: right, on: (l, r) => l.stationID == r.station, as: (l, r) => ({r with last_reported_val: l._value, last_reported_time: l._time}), ) ``` [](#view-example-input-and-output-data) View example input and output data ### Input #### left > [!Note] > *`_start` and `_stop` columns have been omitted.* | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| |2021-08-01T23:59:46.17Z| machinery | g1 |oil\_temp| 40.6 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| |2021-08-01T23:59:34.57Z| machinery | g2 |oil\_temp| 41.34 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|---------|-------| |2021-08-01T23:59:41.96Z| machinery | g3 |oil\_temp| 41.26 | #### right |station|opType| last\_maintained | |-------|------|--------------------| | g1 | auto |2021-07-15T00:00:00Z| | g2 |manned|2021-07-02T00:00:00Z| ### Output |station|opType| last\_maintained | last\_reported\_time |last\_reported\_val| |-------|------|--------------------|-----------------------|-------------------| | g1 | auto |2021-07-15T00:00:00Z|2021-08-01T23:59:46.17Z| 40.6 | | g2 |manned|2021-07-02T00:00:00Z|2021-08-01T23:59:34.57Z| 41.34 | #### Related * [Troubleshoot join operations](/flux/v0/join-data/troubleshoot-joins/) * [join package](/flux/v0/stdlib/join/) * [join.right() function](/flux/v0/stdlib/join/right/) | | | | | --- | --- | --- | | | | | | r1 | ● | ● | | r2 | ● | ● | | | | | | --- | --- | --- | | | | | | r1 | ▲ | ▲ | | r3 | ▲ | ▲ | | r4 | ▲ | ▲ | | | | | | | | --- | --- | --- | --- | --- | | | | | | | | r1 | ● | ● | ▲ | ▲ | | r3 | | | ▲ | ▲ | | r4 | | | ▲ | ▲ | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T23:59:46.17Z | machinery | g1 | oil_temp | 40.6 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T23:59:34.57Z | machinery | g2 | oil_temp | 41.34 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T23:59:41.96Z | machinery | g3 | oil_temp | 41.26 | | station | opType | last_maintained | | --- | --- | --- | | station | opType | last_maintained | | g1 | auto | 2021-07-15T00:00:00Z | | g2 | manned | 2021-07-02T00:00:00Z | | station | opType | last_maintained | last_reported_time | last_reported_val | | --- | --- | --- | --- | --- | | station | opType | last_maintained | last_reported_time | last_reported_val | | g1 | auto | 2021-07-15T00:00:00Z | 2021-08-01T23:59:46.17Z | 40.6 | | g2 | manned | 2021-07-02T00:00:00Z | 2021-08-01T23:59:34.57Z | 41.34 | --- # Join on time Source: https://docs.influxdata.com/flux/v0/join-data/time/ Use [`join.time()`](/flux/v0/stdlib/join/time/) to join two streams of data based on time values in the `_time` column. This type of join operation is common when joining two streams of[time series data](/influxdb/v2/reference/glossary/#time-series-data). `join.time()` can use any of the available join methods. Which method you use depends on your desired behavior: * **inner** *(Default)*: Drop any rows from both input streams that do not have a matching row in the other stream. * **left**: Output a row for each row in the **left** data stream with data matching from the **right** data stream. If there is no matching data in the **right**data stream, non-group-key columns with values from the **right** data stream are *null*. * **right**: Output a row for each row in the **right** data stream with data matching from the **left** data stream. If there is no matching data in the **left**data stream, non-group-key columns with values from the **left** data stream are *null*. * **full**: Output a row for all rows in both the **left** and **right** input streams and join rows that match based on their `_time` value. ## Use join.time to join your data 1. Import the `join` package. 2. Define the **left** and **right** data streams to join: * Each stream must also have a `_time` column. * Each stream must have one or more columns with common values. Column labels do not need to match, but column values do. * Each stream should have identical [group keys](/flux/v0/get-started/data-model/#group-key). *For more information, see [join data requirements](/flux/v0/join-data/#data-requirements).* 3. Use `join.time()` to join the two streams together based on time values. Provide the following parameters: * `left`: (Required) Stream of data representing the left side of the join. * `right`: (Required) Stream of data representing the right side of the join. * `as`: (Required) [Join output function](/flux/v0/join-data/#join-output-function-as)that returns a record with values from each input stream. For example: `(l, r) => ({r with column1: l.column1, column2: l.column2})`. * `method`: Join method to use. Default is `inner`. The following example uses a filtered selections from the[**machineProduction** sample data set](/flux/v0/stdlib/influxdata/influxdb/sample/data/#set)as the **left** and **right** data streams. > [!Note] > #### Example data grouping > > The example below regroups both the left and right streams to remove the`_field` column from the group key. > Because `join.time()` only compares tables with matching[group key instances](/flux/v0/get-started/data-model/#example-group-key-instances), > to join streams with different `_field` column values, `_field` cannot be part > of the group key. ```js import "influxdata/influxdb/sample" import "join" left = sample.data(set: "machineProduction") |> filter(fn: (r) => r.stationID == "g1" or r.stationID == "g2" or r.stationID == "g3") |> filter(fn: (r) => r._field == "pressure") |> limit(n: 5) |> group(columns: ["_time", "_value", "_field"], mode: "except") right = sample.data(set: "machineProduction") |> filter(fn: (r) => r.stationID == "g1" or r.stationID == "g2" or r.stationID == "g3") |> filter(fn: (r) => r._field == "pressure_target") |> limit(n: 5) |> group(columns: ["_time", "_value", "_field"], mode: "except") join.time(method: "left", left: left, right: right, as: (l, r) => ({l with target: r._value})) ``` [](#view-example-input-and-output-data) View example input and output data ### Input > [!Note] > *`_start` and `_stop` columns have been omitted from input examples.* #### left | \_time |\_measurement|stationID|\_field |\_value | |-----------------------|-------------|---------|--------|--------| | 2021-08-01T00:00:00Z | machinery | g1 |pressure|110.2617| |2021-08-01T00:00:11.51Z| machinery | g1 |pressure|110.3506| |2021-08-01T00:00:19.53Z| machinery | g1 |pressure|110.1836| |2021-08-01T00:00:25.1Z | machinery | g1 |pressure|109.6387| |2021-08-01T00:00:36.88Z| machinery | g1 |pressure|110.5021| | \_time |\_measurement|stationID|\_field |\_value | |-----------------------|-------------|---------|--------|--------| | 2021-08-01T00:00:00Z | machinery | g2 |pressure|105.392 | |2021-08-01T00:00:27.93Z| machinery | g2 |pressure|105.3786| |2021-08-01T00:00:54.96Z| machinery | g2 |pressure|105.4801| |2021-08-01T00:01:17.27Z| machinery | g2 |pressure|105.5656| |2021-08-01T00:01:41.84Z| machinery | g2 |pressure|105.5495| | \_time |\_measurement|stationID|\_field |\_value | |-----------------------|-------------|---------|--------|--------| | 2021-08-01T00:00:00Z | machinery | g3 |pressure|110.5309| |2021-08-01T00:00:14.46Z| machinery | g3 |pressure|110.3746| |2021-08-01T00:00:25.29Z| machinery | g3 |pressure|110.3719| |2021-08-01T00:00:38.77Z| machinery | g3 |pressure|110.5362| |2021-08-01T00:00:51.2Z | machinery | g3 |pressure|110.4514| #### right | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|----------------|-------| | 2021-08-01T00:00:00Z | machinery | g1 |pressure\_target| 110 | |2021-08-01T00:00:11.51Z| machinery | g1 |pressure\_target| 110 | |2021-08-01T00:00:19.53Z| machinery | g1 |pressure\_target| 110 | |2021-08-01T00:00:25.1Z | machinery | g1 |pressure\_target| 110 | |2021-08-01T00:00:36.88Z| machinery | g1 |pressure\_target| 110 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|----------------|-------| | 2021-08-01T00:00:00Z | machinery | g2 |pressure\_target| 105 | |2021-08-01T00:00:27.93Z| machinery | g2 |pressure\_target| 105 | |2021-08-01T00:00:54.96Z| machinery | g2 |pressure\_target| 105 | |2021-08-01T00:01:17.27Z| machinery | g2 |pressure\_target| 105 | |2021-08-01T00:01:41.84Z| machinery | g2 |pressure\_target| 105 | | \_time |\_measurement|stationID| \_field |\_value| |-----------------------|-------------|---------|----------------|-------| | 2021-08-01T00:00:00Z | machinery | g3 |pressure\_target| 110 | |2021-08-01T00:00:14.46Z| machinery | g3 |pressure\_target| 110 | |2021-08-01T00:00:25.29Z| machinery | g3 |pressure\_target| 110 | |2021-08-01T00:00:38.77Z| machinery | g3 |pressure\_target| 110 | |2021-08-01T00:00:51.2Z | machinery | g3 |pressure\_target| 110 | ### Output | \_time |\_measurement|stationID|\_field |\_value |target| |-----------------------|-------------|---------|--------|--------|------| | 2021-08-01T00:00:00Z | machinery | g1 |pressure|110.2617| 110 | |2021-08-01T00:00:11.51Z| machinery | g1 |pressure|110.3506| 110 | |2021-08-01T00:00:19.53Z| machinery | g1 |pressure|110.1836| 110 | |2021-08-01T00:00:25.1Z | machinery | g1 |pressure|109.6387| 110 | |2021-08-01T00:00:36.88Z| machinery | g1 |pressure|110.5021| 110 | | \_time |\_measurement|stationID|\_field |\_value |target| |-----------------------|-------------|---------|--------|--------|------| | 2021-08-01T00:00:00Z | machinery | g2 |pressure|105.392 | 105 | |2021-08-01T00:00:27.93Z| machinery | g2 |pressure|105.3786| 105 | |2021-08-01T00:00:54.96Z| machinery | g2 |pressure|105.4801| 105 | |2021-08-01T00:01:17.27Z| machinery | g2 |pressure|105.5656| 105 | |2021-08-01T00:01:41.84Z| machinery | g2 |pressure|105.5495| 105 | | \_time |\_measurement|stationID|\_field |\_value |target| |-----------------------|-------------|---------|--------|--------|------| | 2021-08-01T00:00:00Z | machinery | g3 |pressure|110.5309| 110 | |2021-08-01T00:00:14.46Z| machinery | g3 |pressure|110.3746| 110 | |2021-08-01T00:00:25.29Z| machinery | g3 |pressure|110.3719| 110 | |2021-08-01T00:00:38.77Z| machinery | g3 |pressure|110.5362| 110 | |2021-08-01T00:00:51.2Z | machinery | g3 |pressure|110.4514| 110 | #### Related * [Troubleshoot join operations](/flux/v0/join-data/troubleshoot-joins/) * [join package](/flux/v0/stdlib/join/) * [join.time() function](/flux/v0/stdlib/join/time/) | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g1 | pressure | 110.2617 | | 2021-08-01T00:00:11.51Z | machinery | g1 | pressure | 110.3506 | | 2021-08-01T00:00:19.53Z | machinery | g1 | pressure | 110.1836 | | 2021-08-01T00:00:25.1Z | machinery | g1 | pressure | 109.6387 | | 2021-08-01T00:00:36.88Z | machinery | g1 | pressure | 110.5021 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g2 | pressure | 105.392 | | 2021-08-01T00:00:27.93Z | machinery | g2 | pressure | 105.3786 | | 2021-08-01T00:00:54.96Z | machinery | g2 | pressure | 105.4801 | | 2021-08-01T00:01:17.27Z | machinery | g2 | pressure | 105.5656 | | 2021-08-01T00:01:41.84Z | machinery | g2 | pressure | 105.5495 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g3 | pressure | 110.5309 | | 2021-08-01T00:00:14.46Z | machinery | g3 | pressure | 110.3746 | | 2021-08-01T00:00:25.29Z | machinery | g3 | pressure | 110.3719 | | 2021-08-01T00:00:38.77Z | machinery | g3 | pressure | 110.5362 | | 2021-08-01T00:00:51.2Z | machinery | g3 | pressure | 110.4514 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g1 | pressure_target | 110 | | 2021-08-01T00:00:11.51Z | machinery | g1 | pressure_target | 110 | | 2021-08-01T00:00:19.53Z | machinery | g1 | pressure_target | 110 | | 2021-08-01T00:00:25.1Z | machinery | g1 | pressure_target | 110 | | 2021-08-01T00:00:36.88Z | machinery | g1 | pressure_target | 110 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g2 | pressure_target | 105 | | 2021-08-01T00:00:27.93Z | machinery | g2 | pressure_target | 105 | | 2021-08-01T00:00:54.96Z | machinery | g2 | pressure_target | 105 | | 2021-08-01T00:01:17.27Z | machinery | g2 | pressure_target | 105 | | 2021-08-01T00:01:41.84Z | machinery | g2 | pressure_target | 105 | | _time | _measurement | stationID | _field | _value | | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | | 2021-08-01T00:00:00Z | machinery | g3 | pressure_target | 110 | | 2021-08-01T00:00:14.46Z | machinery | g3 | pressure_target | 110 | | 2021-08-01T00:00:25.29Z | machinery | g3 | pressure_target | 110 | | 2021-08-01T00:00:38.77Z | machinery | g3 | pressure_target | 110 | | 2021-08-01T00:00:51.2Z | machinery | g3 | pressure_target | 110 | | _time | _measurement | stationID | _field | _value | target | | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | target | | 2021-08-01T00:00:00Z | machinery | g1 | pressure | 110.2617 | 110 | | 2021-08-01T00:00:11.51Z | machinery | g1 | pressure | 110.3506 | 110 | | 2021-08-01T00:00:19.53Z | machinery | g1 | pressure | 110.1836 | 110 | | 2021-08-01T00:00:25.1Z | machinery | g1 | pressure | 109.6387 | 110 | | 2021-08-01T00:00:36.88Z | machinery | g1 | pressure | 110.5021 | 110 | | _time | _measurement | stationID | _field | _value | target | | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | target | | 2021-08-01T00:00:00Z | machinery | g2 | pressure | 105.392 | 105 | | 2021-08-01T00:00:27.93Z | machinery | g2 | pressure | 105.3786 | 105 | | 2021-08-01T00:00:54.96Z | machinery | g2 | pressure | 105.4801 | 105 | | 2021-08-01T00:01:17.27Z | machinery | g2 | pressure | 105.5656 | 105 | | 2021-08-01T00:01:41.84Z | machinery | g2 | pressure | 105.5495 | 105 | | _time | _measurement | stationID | _field | _value | target | | --- | --- | --- | --- | --- | --- | | _time | _measurement | stationID | _field | _value | target | | 2021-08-01T00:00:00Z | machinery | g3 | pressure | 110.5309 | 110 | | 2021-08-01T00:00:14.46Z | machinery | g3 | pressure | 110.3746 | 110 | | 2021-08-01T00:00:25.29Z | machinery | g3 | pressure | 110.3719 | 110 | | 2021-08-01T00:00:38.77Z | machinery | g3 | pressure | 110.5362 | 110 | | 2021-08-01T00:00:51.2Z | machinery | g3 | pressure | 110.4514 | 110 | --- # Troubleshoot join operations Source: https://docs.influxdata.com/flux/v0/join-data/troubleshoot-joins/ Learn how to troubleshoot common behaviors and errors that may occur when using the [`join` package](/flux/v0/stdlib/join). > [!Note] > #### Submit issues for unexplained behaviors or errors > > This is a “living” document that may be updated with common issues > that users may run into when using the [`join` package](/flux/v0/stdlib/join). > If you have questions about a behavior or error that is not documented here, > please submit an issue to either the InfluxData Documentation or Flux GitHub repositories: > > * [Submit a documentation issue](https://github.com/influxdata/docs-v2/issues/new/choose) > * [Submit a Flux issue](https://github.com/influxdata/flux/issues/new/choose) * [Troubleshoot join behaviors](#troubleshoot-join-behaviors) * [Troubleshoot join error messages](#troubleshoot-join-error-messages) ## Troubleshoot join behaviors ### Columns explicitly mapped in the join are null In some cases, your join output may include *null* values in columns where you expect non-null values. This may be caused by one of the following issues: #### Cause **The group keys of each input stream aren’t the same.**Functions in the `join` package use group keys to quickly identify what tables should be compared. #### Solution Use [`group()`](/flux/v0/stdlib/universe/group/) to regroup your two input streams so their group keys match before attempting to join them together. #### Cause **There are no matching *group key instances* in your data streams**. Functions in the `join` package only compare tables with matching[group key instances](/flux/v0/get-started/data-model/#example-group-key-instances). Input streams may have matching group keys, but there are no matching group key instances in your stream. This may happen when joining two separate fields queried from InfluxDB. By default, InfluxDB returns data with `_field` as part of the group key. If each stream contains a different field, tables in the two streams won’t be compared because they won’t have any matching *group key instances*. #### Solution Use [`group()`](/flux/v0/stdlib/universe/group/) to remove any columns from the group keys of each input stream that would prevent group key instances from matching. ## Troubleshoot join error messages * [table is missing column '\'](#table-is-missing-column-column) * [table is missing label \](#table-is-missing-label-label) * [record is missing label \](#record-is-missing-label-label) * [cannot join on an empty table](#cannot-join-on-an-empty-table) ### table is missing column `''` ##### Error message ```js cannot set join columns in left table stream: table is missing column '' ``` #### Cause **Your `on` join predicate uses a column that doesn’t exist**. In the `on` predicate function, you’re trying to compare a column that doesn’t exist in one of your input streams. #### Solution Ensure the columns that you’re comparing in the `on` predicate function exist in the input streams. If necessary, update column names in the predicate function. ### table is missing label `