Query & aggregate time-series
Read raw datapoints back for a window, then roll them up to fixed buckets (hourly averages, daily maxima) for a chart or report. Aggregates and the bucket size are part of the retrieve filter — no separate endpoint.
Raw datapoints for a window
- Java
- Python
- Rust
import java.time.ZonedDateTime;
var filter = new RetrieveFilter();
filter.setExternalId("engine_temperature");
filter.setStart(ZonedDateTime.now().minusDays(1));
filter.setEnd(ZonedDateTime.now());
filter.setLimit(10_000);
var request = new DataRetriever<RetrieveFilter>();
request.setItems(List.of(filter));
client.timeseries().retrieve(request).getItems().forEach(series ->
series.getDatapoints().forEach(p ->
System.out.println(p.getTimestamp() + " = " + p.getValue())));
import datahub_sdk, pandas as pd
rf = datahub_sdk.RetrieveFilter(
ts="engine_temperature",
start=pd.Timestamp.now(tz="UTC") - pd.Timedelta(days=1),
end=pd.Timestamp.now(tz="UTC"),
limit=10_000)
for dp in client.timeseries.retrieve_datapoints(rf)[0].get_datapoints():
print(dp.timestamp, dp.value)
use chrono::Utc;
use dataplatform_rust_sdk::generic::{DataWrapper, RetrieveFilter};
let filter = RetrieveFilter {
external_id: Some("engine_temperature".into()),
start: Some(Utc::now() - chrono::Duration::days(1)),
end: Some(Utc::now()),
limit: Some(10_000),
..Default::default()
};
let result = api.time_series.retrieve_datapoints(&DataWrapper::from(vec![filter])).await?;
for series in result.get_items() {
for p in &series.datapoints {
println!("{} = {}", p.timestamp, p.value);
}
}
Hourly averages
Set aggregates and granularity and the server returns one value per bucket.
- Java
- Python
- Rust
var filter = new RetrieveFilter();
filter.setExternalId("engine_temperature");
filter.setStart(ZonedDateTime.now().minusDays(1));
filter.setEnd(ZonedDateTime.now());
filter.setAggregates(List.of("avg", "max"));
filter.setGranularity("1h");
var request = new DataRetriever<RetrieveFilter>();
request.setItems(List.of(filter));
// NOTE: Java can't read aggregate values yet — getValue() returns null here (see warning below)
client.timeseries().retrieve(request).getItems()
.forEach(s -> s.getDatapoints().forEach(p ->
System.out.println(p.getTimestamp() + " = " + p.getValue())));
rf = datahub_sdk.RetrieveFilter(
ts="engine_temperature",
start=pd.Timestamp.now(tz="UTC") - pd.Timedelta(days=1),
end=pd.Timestamp.now(tz="UTC"),
aggregates=["avg", "max"],
granularity="1h")
for dp in client.timeseries.retrieve_datapoints(rf)[0].get_datapoints():
print(dp.timestamp, dp.average, dp.max)
use chrono::Utc;
let filter = RetrieveFilter {
external_id: Some("engine_temperature".into()),
start: Some(Utc::now() - chrono::Duration::days(1)),
end: Some(Utc::now()),
aggregates: Some(vec!["avg".into(), "max".into()]),
granularity: Some("1h".into()),
..Default::default()
};
let result = api.time_series.retrieve_datapoints(&DataWrapper::from(vec![filter])).await?;
for series in result.get_items() {
for p in &series.datapoints {
println!("{} avg={:?} max={:?}", p.timestamp, p.average, p.max);
}
}
avg, min, max, sum. Granularity is a number plus a unit —
30s, 5m, 1h, 1d. The Python and Rust datapoint types expose each requested
aggregate as its own field — min/max/sum by name, and avg read back on
.average (dp.average, dp.max, …).
The Java client does not expose aggregate values yet: getValue() returns null
for aggregated datapoints (the server sends avg/max/… as named fields, but the Java
datapoint type carries only timestamp/value). For now use Python or Rust for
aggregates — or in Java, fetch raw datapoints and aggregate them in your application.
Paging large windows
A wide window can exceed one response. When the result carries a cursor, pass it back to fetch the next page.
- Java
- Python
- Rust
String cursor = null;
do {
var filter = new RetrieveFilter();
filter.setExternalId("engine_temperature");
filter.setStart(start);
filter.setEnd(end);
filter.setCursor(cursor);
var request = new DataRetriever<RetrieveFilter>();
request.setItems(List.of(filter));
var page = client.timeseries().retrieve(request).getItems().get(0);
page.getDatapoints().forEach(p -> handle(p));
cursor = page.getNextCursor();
} while (cursor != null);
cursor = None
while True:
rf = datahub_sdk.RetrieveFilter(ts="engine_temperature",
start=start, end=end, cursor=cursor)
page = client.timeseries.retrieve_datapoints(rf)[0]
for dp in page.get_datapoints():
handle(dp)
cursor = page.next_cursor
if not cursor:
break
use chrono::Utc;
let mut cursor: Option<String> = None;
loop {
let filter = RetrieveFilter {
external_id: Some("engine_temperature".into()),
start: Some(Utc::now() - chrono::Duration::days(1)),
end: Some(Utc::now()),
cursor: cursor.clone(),
..Default::default()
};
let page = api.time_series
.retrieve_datapoints(&DataWrapper::from(vec![filter])).await?
.get_items().remove(0);
for p in &page.datapoints { handle(p); }
cursor = page.next_cursor.clone();
if cursor.is_none() { break; }
}