edges, filters by edge type and direction, and returns the linked documents (carrying the edge’s attributes with each result).
Stage Category: APPLY (relationship traversal)Transformation: N documents → M linked documents (optionally including the originating documents)
Traversal under-returned silently until 2026-08-23. It returned HTTP 200
with rows while omitting a linked document, and the omitted edge read back
fully intact in both directions. No error, no warning — a short result was
indistinguishable from a document that genuinely had fewer links.The cause was in the storage layer, not in edges or in this stage: a paged scan
sorted within a page rather than across the whole key range, so linked
documents past the first page were never reached. Fixed shard-side, with no API
change.Verified end to end on a customer deployment: seed documents, add edges by
PATCH, traverse, and a bogus edge type still returning zero rows as the control.
Two time-spaced runs, because a single pass cannot separate a fix from an
intermittent success.If you are on a deployment that predates the fix, the symptom is a result that
is short rather than wrong. Cross-check against the source document’s own
edges, which were always reliable, and treat a traversal result as a lower
bound until a traversal you can predict returns everything you expect.Writing edges was never affected. Edge persistence was fixed separately and
earlier: seeded documents serve, and edges added by PATCH read back intact in
both directions. There has never been a reason to change how you create edges.
When to Use
When NOT to Use
How it works
- For each document entering the stage, the stage reads its root-level
edgeslist. - Edges are kept when their
typematchesedge_typeand theirdirectionmatches the configureddirection. - Each kept edge’s
target_object_idis resolved to the linked document(s); withtarget_collection_idset, only documents from that collection are returned. - Matched documents are returned with the originating edge’s
attributesattached (e.g.clip_order,start_ticks_in/start_ticks_out), so downstream stages can use them.
edge_type and direction.
Creating edges on objects
Edges are customer-owned data written at the root of an object when you create it (never under_internal). They flow automatically from the object,
through your collections, into each document’s search payload — so a stage can
follow them at query time without you re-computing anything.
Pass an edges array to POST /v1/buckets/{bucket_id}/objects:
Parameters
Example
Starting from an ad document, fetch every piece of footage it uses:edge_type also accepts a list to follow several relationship types in a single
stage — e.g. "edge_type": ["uses_footage", "used_in_ad"] returns documents reached
by either edge, each still labelled with its own traversed_via.
Each returned footage document carries the edge attributes from the ad that referenced it — clip_order, start_ticks_in, and start_ticks_out — so you know exactly where in the footage each clip was taken.
The traversed_via response
Every document produced by traversal carries a traversed_via field describing
the edge (or edges) that reached it:
Single source (footage → ad,
used_in_ad) — traversed_via is an object:
uses_footage, where two
ads reference the same footage) — traversed_via is a list:
uses_footage/out from an ad to reach its footage,
or used_in_ad/out from that footage to reach the ads that use it — and the
attributes (clip order, ticks) are identical in both directions.
Related
- Objects — how edges are stored on objects and flow to documents
- Iconik integration — how footage↔ad edges are captured at ingestion
- Cross Compare — match content across collections by similarity instead of saved edges

