Filtering

The filter module provides filter expressions for selecting subsets of nodes and edges based on their attributes, properties, and relationships.

The filter module mirrors Raphtory's APIs. Anything you can do with temporal properties, layers, windows, or metadata can be expressed as a filter. This lets Raphtory handle filtering internally with optimised Rust code rather than requiring Python loops. If you find yourself writing a for-loop to filter entities, there's probably a filter expression that does it faster.

Filtering vs Indexing

There are two ways to apply filters:

  • Indexing (nodes[filter]) — applies a filter once to a collection, returning the matching items as a new collection. The original graph and any relationships remain unchanged, so traversing from filtered nodes still accesses all neighbours and edges.

  • .filter(expr) — creates a persistent filtered view of the graph. The filter propagates through all subsequent operations: accessing edges, neighbours, or properties only returns data that satisfies the filter condition.


Filter Classes

Raphtory provides four filter classes:

Filter ClassPurpose
filter.GraphTime and layer filters
filter.NodeFilter nodes by name, type, id, metadata, properties
filter.EdgeFilter edges by layer, properties, and endpoint attributes
filter.ExplodedEdgeFilter individual edge updates

filter.Graph

filter.Graph supports all view functions from Graph Views. You can filter by time windows, layers, snapshots, and more.

The example shows a social network with edges added at different times across work and social layers. We filter to edges before/after a timestamp, within a time window, and on specific layers.

filter.Node

filter.Node filters nodes by their attributes and properties. You can also chain view functions (like window() or layer()) to filter properties within specific time or layer bounds.

The example creates users with metadata and salary history. We filter by name prefix, node type, metadata values, and demonstrate window() chaining to find nodes where the max salary within a time range meets a condition.

MethodDescription
name()Access node name (supports string operations)
node_type()Access node type
id()Access node ID
metadata(key)Access metadata
property(key)Access temporal properties

filter.Edge

filter.Edge filters edges by their properties and endpoints. The src() and dst() methods let you filter based on source and destination node attributes. Like filter.Node, you can chain view functions to scope property lookups.

The example creates a graph of people and companies with relationship edges. We filter by layer + property conditions, use window() to scope temporal lookups, and filter by source/destination node types and metadata.

MethodDescription
metadata(key)Access metadata
property(key)Access temporal properties
src()Access source node attributes
dst()Access destination node attributes

filter.ExplodedEdge

When you call edge.explode(), each temporal update becomes a separate item. filter.ExplodedEdge lets you filter these individual updates.

The example shows a sensor sending readings to a hub over time. Each reading has a temperature and status. After exploding the edge, we filter individual updates by their property values to find critical readings or readings above a threshold.

If all updates for an edge are filtered out, the edge itself is removed from the result.


Property Filtering

Metadata

Metadata are immutable values set on a node or edge. They don't change over time. Use metadata(key) to filter by these values.

The example below shows sensors with different locations, models, and calibration status. We filter by exact match, use is_in() to match multiple values, is_not_in() to exclude values, and contains() for substring matching. The final filter combines conditions to find calibrated sensors in priority warehouses.

Temporal Property Operations

Temporal properties store multiple values over time. Use .temporal() to access aggregation and quantifier operations that filter based on the entire history of a property, not just its current value.

The example tracks temperature readings from sensors over time, then filters using .max(), .avg(), .any(), and .all() to answer questions like "which sensors ever exceeded 30°C?" or "which sensors always stayed below 25°C?".

OperationDescription
sum()Sum of all values
avg()Average of all values
min(), max()Minimum/maximum value
first(), last()First/most recent value
all()All values must satisfy condition
any()At least one value must satisfy condition
len()Count of updates

Scoping with Window and Layer

When filtering by temporal properties, you can scope the lookup using window() or layer(). This is useful for questions like "which servers had high CPU usage during the incident window?" or "which edges in the work layer have been active recently?"

The pattern is filter.Node.window(start, end).property("key").temporal().aggregation(). Without a window, the filter considers the entire history. With a window, only values within that time range are used for aggregation.

The example tracks CPU usage across servers. During normal operation, usage is low. During a high-traffic window (t=4-11), some servers spike. We compare filtering with and without windows to show how scoping changes the results.

String Operations

For string-valued attributes like names and metadata, you can use string operations to match patterns. These work on name(), node_type(), and string metadata/properties.

OperationDescription
starts_with(prefix)String starts with prefix
ends_with(suffix)String ends with suffix
contains(substring)String contains substring
not_contains(substring)String doesn't contain substring
fuzzy_search(pattern, max_edits, prefix)Fuzzy matching: max_edits = allowed character edits, prefix = required exact prefix length
is_in([...])Value is in list
is_not_in([...])Value is not in list

Checking Property Existence

Use is_some() and is_none() to filter based on whether a property exists. This is useful when properties may be missing on some entities.


Combining Filters

Combine filter expressions with Python's bitwise operators:

OperatorMeaning
&AND — both conditions must be true
|OR — at least one condition must be true
~NOT — negates the condition

You must use bitwise operators &, |, and ~. Python's and, or, and not keywords do not work with filter expressions.

The example creates users with admin/user types and active/inactive status. We define base filters for admin and active, then combine them to find active admins, inactive admins, and active non-admins.


The Prop Type

When filtering on properties with specific internal types, use the Prop class to create typed values for comparison. This is essential when properties are stored as types Python doesn't have natively (like u8 or f32).

Type ConstructorDescription
Prop.bool(v)Boolean
Prop.str(v)String
Prop.u8(v), Prop.u16(v), Prop.u32(v), Prop.u64(v)Unsigned integers (8, 16, 32, 64-bit)
Prop.i32(v), Prop.i64(v)Signed integers (32, 64-bit)
Prop.f32(v), Prop.f64(v)Floating point (32, 64-bit)
Prop.list(v)List of values
Prop.map(v)Dictionary/map

Comparison operators: ==, !=, <, <=, >, >=