Chaining Queries
The Raphtory iterables Nodes, Edges, and Properties are lazy data structures which allow you to chain multiple functions together before a final execution.
For a node v, using the chain v.neighbours.neighbours will return the two-hop neighbours. The first call of neighbours returns the immediate neighbours of v, the second applies the neighbours function to each of the nodes returned by the first call.
You can continue this chain indefinitely with any functions in the Node, Edge, or Properties API until either:
- Calling
.collect(), which will execute the chain and return the result. - Executing the chain by handing it to a Python function such as
list(),set(),sum(), etc. - Iterating through the chain via a loop or list comprehension.
The following example gets the names of all the baboons and their two-hop neighbours:
Views vs Filters in Chains
Raphtory provides two distinct approaches for restricting data in chains, each with different persistence semantics:
- Views persist — Operations like
window()orlayers()create a restricted view of the graph that applies to all subsequent operations in the chain. Once you create a view, it affects everything to the right of it. - Filters are one-off — Using
[]with filter expressions applies a restriction to only that specific step in the chain.
The following example demonstrates three approaches using a time window:
- View-based:
g.node("FELIPE").window(start, end).neighbours— Creates a view of Felipe restricted to the time window, and all returned neighbours are also restricted to that window. - Neighbour filter:
g.node("FELIPE").neighbours[filter.Graph.window(start, end)]— Returns neighbours that were active in the time window, but the returned nodes have their full history available (no view restriction). - Edge filter:
g.node("FELIPE").edges[filter.Graph.window(start, end)].nbr— Returns nodes that Felipe interacted with during the time window, but again with no view restriction on the returned nodes.
Notice in the output how the view-based approach restricts the neighbour's time range to within the window, while the filter-based approaches return nodes with their full history intact.
Chains with properties
To demonstrate more complex queries using Raphtory, the following example combines property aggregation with chains.
First we sum the Weight value of each of Felipe's out-neighbours to rank them by positive interactions he has initiated. Then we find the "most annoying" monkey by ranking who, on average, has had the most negative interactions initiated against them.
The chain g.nodes.in_edges.properties.temporal.get("Weight").values().sum().mean() demonstrates the power of lazy evaluation — we're aggregating across all nodes, their incoming edges, and the temporal property values, all without materializing intermediate results.
Multi-layer Temporal Traversal
Filters can be combined using & to create powerful multi-step queries. In this example, we're investigating baboon social dynamics: who played with Felipe in the first week, and who did those playmates rest with in the following week?
By chaining in_edges[week_1 & playing].nbr.out_edges[week_2 & resting], we traverse from Felipe through his play partners to their resting companions — each step filtered by both time window and interaction type, with property aggregation on the final edges.