Querying a time series
Reading a time series is a POST with a JSON body, like every other OpenGate query:
Copy this and change the identifiers:
The response is a columns array naming the fields and a data array of rows in that order:
The request body
| Clause | Accepts |
|---|---|
filter |
The standard operators, keyed by bucketColumn, identifierColumn, columns.name or context.name |
sort |
A string: the identifier of one of the sorts declared in the time series, not a list of fields |
select |
The same keys as filter |
limit |
start and size, as everywhere else |
Two things differ from a plain Data Lake search, and both come from the time series being pre-computed: you can only filter on columns declared filterable, and you can only sort by sorts declared in the definition. See Defining a time series for how those are declared, and Query dialects for the full comparison.
Column order when you omit select
columns tells you the order, so read values off it rather than hardcoding positions. If you do depend on
the order, it is:
- The
bucketColumn, holding the end date of the bucket - The
identifierColumn, holdingprovision.administration.identifier._current.value - The
contextcolumns - The aggregated
columns
Asking for a sort
You do not compose an ordering in the request. You name one that already exists:
Valid values are the identifier of any sort in the time series definition, plus the automatically
exposed reverse of each one. So a definition declaring bucket_id_desc gives you both directions without
declaring the second.
Read the definition to see what is available — GET the time series, or use expand=sorts, and the sorts
list comes back with the derived ones included. There is no fixed limit on how many sorts a definition can
hold; the constraint is the optimization unit budget, described in
Defining a time series.
Pagination and CSV
The response format changes what limit means, which catches people out:
| Body | JSON | CSV |
|---|---|---|
{"filter": {}, "limit": {"size": 500, "start": 1}} |
500 rows from row 1 | 500 rows from row 1 |
{"filter": {}} |
Configured default page | Everything |
{"filter": {}, "limit": {}} |
Configured default page | Error — an incomplete limit is rejected |
CSV retrieval also turns sorting off, deliberately, so that large exports stay fast. If you need ordered output, sort downstream or read JSON.
Complete retrieval is expensive
Omitting limit in CSV mode downloads the whole time series. Page it unless you truly want everything.
The CSV formatting itself — quoting character, escape character, end-of-line sequence and how nulls are represented — is set through HTTP header options, and you are responsible for the result being well-formed. The exact header names are not currently published, so ask your platform contact for them.
Aggregated read: one row per device
Besides reading buckets, you can collapse every bucket of a device into a single row:
Here select.columns describes the output variables, each with the source column, an alias for the
output name, and the aggregation function to apply across buckets:
filter and limit behave as above, and CSV output is available too. Two rules are specific to this
endpoint:
- The output is always sorted ascending by
identifierColumn. - The
identifierColumnis always included, added as the first column if you did not ask for it.
Parquet export
For bulk analytical work, a time series can be exported to a Parquet file:
POST starts the export, GET reports the state of the current one. The output order is decided
internally and cannot be changed.