@CDRW When aggregateWindow
determines interval boundaries, it does so using logical boundary steps. For example, 10s
interval will generate window boundaries on 00:00:00, 00:00:10, 00:00:20, … etc. However, in range()
, the start time is relative to now. So if right now is 00:00:23, the range of the query covers 00:00:13 to 00:00:23. This actually spans across two logical window boundaries, so you get two results.
When it comes to the output timestamps, by default, aggregateWindow()
uses 1) the stop boundary for the window or 2) if the stop boundary is outside of the query range, the stop boundary of the query. That is why the two output timestamps are 2023-12-05T02:22:20 and 2023-12-05T02:22:23.
So really anytime you manually run this query, it will return two results (unless you somehow manage to run it on the exact nanosecond of a logical time boundary). However, if you’re going to be running this query as a task, the task engine schedules tasks on logical time boundaries, so you shouldn’t have this issue.
But if you want to protect against this and make sure your query range always falls on logical time boundaries (even when you manually execute it), you can override the start and stop query boundaries to use timestamps truncated to the latest 10s time.
import "date"
interval = 10s
truncatedNow = date.truncate(t: now(), unit: interval)
start = date.sub(d: interval, from: truncatedNow)
stop = truncatedNow
from(bucket: "main")
|> range(start: start, stop: stop)
|> filter(fn: (r) => r["_measurement"] == "measurements")
|> aggregateWindow(every: interval, fn: mean, createEmpty: true)