For the complete documentation index optimized for AI agents, see llms.txt.This page covers the steps that narrow a stream rather than walking the graph: property and label filters, the full
Predicate catalog, ordering, and slicing the
result with limit / skip / range.
.has, .hasLabel, .hasKey
The simplest filters are equality checks on a single property. They work on both
node and edge streams.
.has(property, value)— property equals the given value..hasLabel(label)— node/edge label equals..hasKey(property)— property exists (any non-null value).
.where(...).
.where(Predicate.*)
For anything richer than equality, use .where(Predicate.*). Predicate exposes the
full set:
| Group | Builders |
|---|---|
| Comparison | eq, neq, gt, gte, lt, lte, between |
| String | startsWith, endsWith, contains |
| Collection | isIn, isInExpr |
| Property presence | hasKey, isNull, isNotNull |
| Logical | and([...]), or([...]), not(p) |
| Parameter-bound | eqParam, neqParam, gtParam, gteParam, ltParam, lteParam, isInParam, containsParam |
| Expression | compare(left, op, right) — for arithmetic on either side |
SourcePredicate vs Predicate
Use a SourcePredicate at source steps when the filter should participate in index
selection; use .where(Predicate.*) for anything outside that set or to filter after a
traversal step. See
SourcePredicate vs Predicate
for the full breakdown.
Nested property paths
Object properties can be filtered with dotted paths. The runtime first checks for an exact top-level property name, then walks nested object fields when the name contains..
metadata.tags.0 is not supported.
Parameter-bound predicates
To filter by a value the caller supplies at request time, use the*Param family.
Pass the parameter name as a string; the runtime substitutes the value at execution.
Full parameter declaration via defineParams is covered on
Parameters & bundles; this page focuses
on the predicate shape.
Predicate.eqParam(prop, name)desugars to a genericComparepredicate with aPropertyon the left and aParamon the right. The same shape applies toneqParam,gtParam,gteParam,ltParam,lteParam(theopfield varies).Predicate.isInParam("status", "statuses")becomes{"IsInExpr": ["status", {"Param": "statuses"}]}— aParam-valued expression, not aCompare.Predicate.containsParam("body", "needle")becomes{"ContainsExpr": ["body", {"Param": "needle"}]}.
Filtering edges in the middle of a traversal
When you’re walking through an edge stream and want to filter on edge properties without leaving the stream, use the same generic filters as node streams:.has(prop, value), .hasLabel(label), .hasKey(prop), and
.where(Predicate.*).
Edge predicates can read stored edge properties plus the virtual edge fields
$id, $label, $from, $to, $distance, and $score. Use .edgeHas(prop, value) when the right-hand side must be a PropertyInput expression or runtime
parameter.
Ordering
.orderBy(property, Order.Asc | Order.Desc) sorts by a single property.
.orderByMultiple([[prop, order], ...]) sorts by several at once with explicit
direction per key.
Paging: .limit, .skip, .range
The three slicing steps all accept either a literal number / bigint or a
StreamBound for parameter-bound bounds.
.limit(n)— keep the firstn..skip(n)— drop the firstn..range(start, end)— keep the half-open[start, end)slice.
Literal bounds
Parameter-bound limits
For request-time pagination, wrap the bound inStreamBound.expr(Expr.param("...")).
The JSON variant changes too: Limit becomes LimitBy, Skip becomes SkipBy,
Range becomes RangeBy.
Range parameter-bound variant looks like:
Literal or an Expr, so you can mix-and-match a
constant start with a parameterized end.
Next Steps
Projections
Choose what the caller sees:
values, valueMap, project, terminal aggregations.Mutations
addN, addE, setProperty, drop — write batches end-to-end.