---
title: nexyron.temporal_rollup
url: https://nexyron.tech/docs/cypher/procedures/temporal-and-streaming/nexyron-temporal-rollup
description: Read one declared rollup tier for one temporal property on one known subject node.
---

# nexyron.temporal_rollup

## Generic Description

Read one declared rollup tier for one temporal property on one known subject node.

Simple example:

```cypher
MATCH (u:User {id: 'user-17'})
CALL nexyron.temporal_rollup(element_id(u), 'weight', 'daily', null, null)
YIELD start_ts, end_ts, aggregates
RETURN start_ts, end_ts, aggregates
ORDER BY start_ts
```

Temporal and streaming procedures inspect registered temporal history, rollups, time ranges, and global event timelines.

## Consumer-Level Explanation

Use `nexyron.temporal_rollup` when you want pre-aggregated buckets for one temporal property instead of scanning the full raw history.

The procedure reads one named rollup tier such as `daily`, `hourly`, or `weekly`, as declared on the temporal property schema.

The first argument is a node key. It accepts either the internal integer `id(node)` or the public node element id string from `element_id(node)`, for example `n:180098582026649600`. Feature contracts whose abstraction `subject_id` is already a node element id can pass `$subject_id` directly; contracts backed by business keys should first match the owner node and pass `element_id(owner)` or `id(owner)`.

The optional time-window arguments accept canonical `i64` epoch-millisecond integers. `currenttimestamp() - 604800000` is a valid lower bound for the previous seven days, and `timestamp()` returns the same integer millisecond format.

When the surrounding query uses `ASOF`, `nexyron.temporal_rollup` is capped by that point-in-time context. Passing `null` as `to` means "up to the ASOF timestamp", and passing a later explicit `to` is treated as `min(to, ASOF)`.

## Conceptual Explanation

Temporal rollups are aggregate side structures over raw temporal-property history. They are not the primary history itself. They exist to make repeated analytical reads cheaper.

`nexyron.temporal_rollup` is the direct way to read those precomputed buckets for:

-   one subject node
-   one property
-   one rollup tier
-   one optional time window

This is the right surface when the user wants max/min/sum/count/last-style buckets and does not need every raw record.

## More Detailed Explanation

In practical queries, start by deciding the row grain you want after the call: one row per node, one row per path, one row per registry object, one row per artifact, or one row per summary. Then keep that grain explicit with `YIELD` and named projections. That is the difference between a useful planner-facing example and a vague call that downstream tooling cannot safely compose. For contract-driven procedures, the executable examples on these pages intentionally inspect procedure metadata unless the required named artifacts are created in the same example.

## Advanced Example

```cypher
MATCH (d:Device {id: 'watch-17'})
WITH element_id(d) AS device_id
CALL nexyron.temporal_rollup(device_id, 'battery_pct', 'hourly', currenttimestamp() - 7 * 24 * 60 * 60 * 1000, null)
YIELD start_ts, end_ts, aggregates
RETURN start_ts, end_ts, aggregates.max AS max_battery, aggregates.last AS last_battery
ORDER BY start_ts
```

## Real Use Cases

-   Read daily max heart rate for one athlete.
-   Read weekly sum of steps for one device owner.
-   Read hourly last-known battery percentage without scanning every raw reading.
-   compose the procedure output with `YIELD`, `WITH`, and `RETURN` rather than hiding follow-up logic outside Cypher

## Real Limitations And Tradeoffs

-   The requested rollup must have been declared on the temporal property.
-   Rollups only expose the aggregates that were materialized for that tier.
-   Under `ASOF`, the rollup read is bounded to buckets at or before the ASOF timestamp.
-   If the user needs exact raw changes, use `nexyron.temporal_history` instead.
