Skip to content

Change temporal values from strings to prop values and add aggregates#2588

Merged
miratepuffin merged 3 commits intodb_v4from
fix/temporal-values
Apr 24, 2026
Merged

Change temporal values from strings to prop values and add aggregates#2588
miratepuffin merged 3 commits intodb_v4from
fix/temporal-values

Conversation

@miratepuffin
Copy link
Copy Markdown
Collaborator

@miratepuffin miratepuffin commented Apr 24, 2026

API changes

GraphQL: typed values for temporal properties (breaking)

TemporalProperty fields that used to return stringified values now return properly typed PropertyOutput scalars (the same one already used by Property.value), so numbers come back as numbers, booleans as booleans, etc.:

Field Before After
values [String!]! [PropertyOutput!]!
latest String PropertyOutput
at(t) String PropertyOutput
unique [String!]! [PropertyOutput!]!

No other fields (including the list-of-Property shape of Properties.values / Metadata.values) are changed.

GraphQL: new aggregation fields on TemporalProperty

Parity with the Python TemporalProperty aggregations, exposed as fields on each temporal property (so they compose with window(...) / layer(...) / etc.):

Field Type Notes
sum PropertyOutput null if dtype isn't additive; strings concatenate in temporal order
mean / average PropertyOutput always F64; null if any value can't be converted to f64
count Int number of updates
min PropertyTuple (time, value) pair; null if dtype isn't comparable
max PropertyTuple (time, value) pair; null if dtype isn't comparable
median PropertyTuple lower median on even-length inputs

Rust core: aggregations promoted to TemporalPropertyView

sum / min / max / count / mean / average / median previously only existed on the Python wrapper (PyTemporalProp) via private helpers. They've been moved onto the core TemporalPropertyView in raphtory::db::api::properties, so pure-Rust consumers get them directly, and Python + GraphQL now share the one implementation.

Tests

New python/tests/test_base_install/test_graphql/test_gql_temporal_aggregates.py:

  • Numeric node property — all aggregations on full timeline, windowed view, and empty-window edge case.
  • Float edge property on two layers — all aggregations under full view, per-layer view, and combined layer + window.
  • Non-numeric semantics — strings (sum concatenates, mean null, min/max/median lexicographic) and bools (sum/mean null, min/max/median work with False < True).

Fixes #2102

Comment on lines +175 to +177
pub fn average(&self) -> Option<Prop> {
self.mean()
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need the alias?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but it has been there for ages and people might be using it

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'Rust Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: 19c6d74 Previous: 9823ef7 Ratio
large/1k random edge additions with numeric string input 1893945 ns/iter (± 272864) 876236 ns/iter (± 86855) 2.16
lotr_graph/num_edges 4 ns/iter (± 0) 0 ns/iter (± 0) +∞
lotr_graph/num_nodes 140 ns/iter (± 45) 1 ns/iter (± 0) 140
lotr_graph/graph_latest 2 ns/iter (± 0) 0 ns/iter (± 0) +∞
lotr_graph_materialise/materialize 3241143 ns/iter (± 30322) 1564816 ns/iter (± 35303) 2.07
lotr_graph_window_100/num_edges 25 ns/iter (± 0) 8 ns/iter (± 0) 3.13
lotr_graph_window_100/num_nodes 161 ns/iter (± 57) 5 ns/iter (± 0) 32.20
lotr_graph_window_100/has_node_existing 45 ns/iter (± 1) 22 ns/iter (± 0) 2.05
lotr_graph_window_100_materialise/materialize 3570264 ns/iter (± 8808) 1669150 ns/iter (± 10700) 2.14
lotr_graph_window_10/has_node_existing 143 ns/iter (± 9) 62 ns/iter (± 11) 2.31
lotr_graph_window_10/iterate nodes 30752 ns/iter (± 64) 11339 ns/iter (± 40) 2.71
lotr_graph_window_10_materialise/materialize 1994079 ns/iter (± 9498) 971980 ns/iter (± 4278) 2.05
lotr_graph_subgraph_10pc/has_edge_existing 233 ns/iter (± 11) 93 ns/iter (± 1) 2.51
lotr_graph_subgraph_10pc/num_nodes 148 ns/iter (± 39) 4 ns/iter (± 0) 37
lotr_graph_subgraph_10pc/has_node_existing 99 ns/iter (± 2) 34 ns/iter (± 0) 2.91
lotr_graph_subgraph_10pc/iterate nodes 2549 ns/iter (± 114) 839 ns/iter (± 5) 3.04
lotr_graph_subgraph_10pc_windowed/has_node_existing 137 ns/iter (± 8) 62 ns/iter (± 14) 2.21
lotr_graph_subgraph_10pc_windowed/iterate nodes 4358 ns/iter (± 109) 1365 ns/iter (± 3) 3.19
lotr_graph_window_50_layered/num_edges_temporal 149468 ns/iter (± 1739) 70121 ns/iter (± 7586) 2.13
lotr_graph_window_50_layered/num_nodes 60129 ns/iter (± 670) 21435 ns/iter (± 536) 2.81
lotr_graph_window_50_layered/has_node_existing 891 ns/iter (± 76) 129 ns/iter (± 12) 6.91
lotr_graph_window_50_layered/max_id 68370 ns/iter (± 604) 25556 ns/iter (± 252) 2.68
lotr_graph_window_50_layered/iterate nodes 113580 ns/iter (± 580) 19308 ns/iter (± 47) 5.88
lotr_graph_window_50_layered/iterate edges 171780 ns/iter (± 307) 83616 ns/iter (± 1318) 2.05
lotr_graph_window_50_layered/graph_latest 101737 ns/iter (± 748) 36649 ns/iter (± 916) 2.78
lotr_graph_window_50_layered_materialise/materialize 7073423 ns/iter (± 88907) 3488825 ns/iter (± 24948) 2.03
lotr_graph_persistent_window_50_layered/num_edges_temporal 756950 ns/iter (± 6779) 192686 ns/iter (± 1569) 3.93
lotr_graph_persistent_window_50_layered/num_nodes 81212 ns/iter (± 1435) 31517 ns/iter (± 779) 2.58
lotr_graph_persistent_window_50_layered/has_node_existing 1034 ns/iter (± 149) 174 ns/iter (± 83) 5.94
lotr_graph_persistent_window_50_layered/max_id 90971 ns/iter (± 746) 38024 ns/iter (± 490) 2.39
lotr_graph_persistent_window_50_layered/iterate nodes 155019 ns/iter (± 905) 35886 ns/iter (± 191) 4.32
lotr_graph_persistent_window_50_layered/iterate edges 168339 ns/iter (± 283) 84161 ns/iter (± 596) 2.00
lotr_graph_persistent_window_50_layered/graph_latest 165940 ns/iter (± 2780) 57549 ns/iter (± 4809) 2.88
lotr_graph_persistent_window_50_layered_materialise/materialize 13663360 ns/iter (± 128211) 5298035 ns/iter (± 147912) 2.58
lotr_graph/proto_encode 4791594 ns/iter (± 49562) 1157897 ns/iter (± 73709) 4.14

This comment was automatically generated by workflow using github-action-benchmark.

@miratepuffin miratepuffin merged commit a72dcfd into db_v4 Apr 24, 2026
6 checks passed
@miratepuffin miratepuffin deleted the fix/temporal-values branch April 24, 2026 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add aggregates to graphql propery APIs

2 participants