Skip to content

feat(query): streaming IterNodes terminal and edge-predicate filtering#4

Merged
mlwelles merged 9 commits into
mainfrom
feature/query-iternodes
May 21, 2026
Merged

feat(query): streaming IterNodes terminal and edge-predicate filtering#4
mlwelles merged 9 commits into
mainfrom
feature/query-iternodes

Conversation

@mlwelles
Copy link
Copy Markdown
Owner

Lands the query-builder work from feature/query-iternodes onto the fork's
main — two complete features plus their design specs (9 commits; main was
behind by the whole IterNodes line).

Edge-predicate filtering (new)

<Entity>Query can now filter root records by a scalar predicate of a
neighbouring node reached over an edge — e.g. directors who directed a film
named "Inception":

client.Director.Query(ctx).WhereFilms(`eq(name, "Inception")`).Nodes()

dgraph's root @filter cannot express this (it only sees the root node's own
predicates), so a query carrying WhereEdge constraints runs a two-step
semi-join
: a @cascade pre-pass resolves the matching root UIDs, then the
main query is re-pointed at uid(...). Step two stays entirely on the dgman
path, so ordering, pagination, IterNodes, and reverse-edge-aware projection
all keep working unchanged.

  • typed.Query[T].WhereEdge(predicate, filter, params...) — handwritten substrate
  • generated <Entity>Query.Where<Edge>(filter, params...) — one per edge field
  • Multiple Where* calls AND together; composes with Filter/OrderAsc/Limit/…
  • String-filter API for v1 (mirrors Filter); a typed predicate DSL is future work
  • Design: docs/specs/2026-05-21-query-edge-filter-design.md

Streaming IterNodes (already on the branch)

typed.Query[T].IterNodes() and the generated <Entity>Query.IterNodes() — a
streaming terminal that pages results instead of materializing them, with
Client.Iter unified onto it. Design:
docs/specs/2026-05-21-query-iternodes-design.md. A third design spec (untyped
query operations) is included as design-only, no implementation.

Test plan

  • go test ./typed/... — green (IterNodes suite + 7 new WhereEdge behavioral tests)
  • go test ./cmd/modusgraph-gen/... and the movies fixture package — green
    (new TestGenerate_WrapperQueryEdgeFilter; new TestWrapperQuery_WhereEdgeFiltersByEdgeTarget e2e)
  • go vet ./... and go build ./... — clean

mlwelles added 9 commits May 21, 2026 17:42
Design for typed.Query[T].IterNodes() — a streaming counterpart to Nodes()
that pages results instead of materializing them. Records the decisions to
respect caller-set Limit/Offset (Query[T] tracks its own bounds) and to
unify Client.Iter onto the new terminal.
Adds typed.Query[T].WhereEdge — filter root records by a scalar predicate of
a node reached over an outbound edge ("owners who have a pet named Fido").
dgman renders one query block with no per-edge @filter, so a query carrying
edge constraints runs as a two-step semi-join: an @cascade pre-pass resolves
the matching root UIDs, then the main query runs against uid(...), keeping
ordering, pagination, IterNodes paging, and result projection on the normal
dgman path.

The generator emits one thin <Entity>Query.Where<Edge> method per edge field,
delegating to the WhereEdge substrate. Regenerates the movies fixture; adds
tests at the typed, generator, and wrapper-e2e layers.

See docs/specs/2026-05-21-query-edge-filter-design.md.
@mlwelles mlwelles merged commit b55d651 into main May 21, 2026
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.

1 participant