Query Engine

This document describes Graphite’s fluent query engine. Queries start from engine.query and return a chainable QueryResult object.

The entry point is the QueryBuilder, which allows starting a query from a node type.


Starting a Query

You can start a query from a node type:

engine.query.Person
engine.query.Company

Accessing engine.query.Person returns all nodes whose type is Person.

To start from all nodes:

engine.query.all()

If the node type does not exist, a NotFoundError is raised.


Filtering

where()

Filters nodes using either:

  • A string condition
  • A callable (lambda)

String Condition

engine.query.Person.where("age >= 18")
engine.query.Person.where("name == 'Alice'")

Supported operators:

  • == or =
  • !=
  • >
  • <
  • >=
  • <=

Date fields are parsed using YYYY-MM-DD format.

Lambda Condition

engine.query.Person.where(lambda n: n.get("age") > 18)

If the condition fails to evaluate, a ConditionError is raised.


with_type()

Filter by exact node type:

engine.query.all().with_type("Person")

with_fields()

Filter nodes that contain specific fields:

engine.query.all().with_fields("name", "age")

Traversal

Traversal moves across relations and returns connected nodes.

Outgoing

engine.query.Person.outgoing("WORKS_AT")

Equivalent to:

engine.query.Person.traverse("WORKS_AT", direction="outgoing")

Incoming

engine.query.Company.incoming("WORKS_AT")

Both Directions

engine.query.Person.both("FRIEND_OF")

If no relation type is provided, all relation types are considered.

Traversal returns a new QueryResult containing:

  • Connected nodes
  • Traversed relations

Result Control

limit()

engine.query.Person.limit(10)

paginate()

engine.query.Person.paginate(page=2, per_page=10)

distinct()

Removes duplicate nodes:

engine.query.Person.outgoing("WORKS_AT").distinct()

order_by()

engine.query.Person.order_by("age")
engine.query.Person.order_by("age", descending=True)

Aggregation

count()

engine.query.Person.count()

sum()

engine.query.Person.sum("salary")

Non-numeric values are ignored.


avg()

engine.query.Person.avg("age")

min() / max()

engine.query.Person.min("age")
engine.query.Person.max("age")

group_by()

engine.query.Person.group_by("age")

Returns a dictionary mapping field values to lists of nodes.


Combining Queries

union()

q1 = engine.query.Person.where("age > 30")
q2 = engine.query.Person.where("age < 20")

q1.union(q2)

May produce duplicates; use .distinct() if necessary.


exclude()

engine.query.Person.exclude(
    engine.query.Person.where("age < 18")
)

intersect()

engine.query.Person.where("age > 18").intersect(
    engine.query.Person.where("age < 30")
)

Tip

This query is implemented for complex use cases; for simple cases, it is recommended to use .where() chains: python engine.query.Person.where("age > 18").where("age < 30")


Mutations

Important

"Mutation" queries directly apply their effects to the engine. To remove findings from the query (and not actually delete nodes and relationships from the engine), you can use .exclude() (ramove) and .intersect() (select).

set()

Updates field values on all result nodes:

engine.query.Person.where("name == 'Alice'").set_val(age=30)

Changes are applied directly to the engine.

If a field does not exist, a NotFoundError is raised.


remove()

Removes result nodes:

engine.query.Person.where("age < 0").remove()

remove_relations()

Removes relations in the current result:

engine.query.Person.outgoing("WORKS_AT").remove_relations()

Accessing Results

Get Nodes

nodes = engine.query.Person.get()

First Result

node = engine.query.Person.first()

Get IDs

ids = engine.query.Person.ids()

Get Relations

relations = engine.query.Person.outgoing("WORKS_AT").relations()

Execution Model

  • Queries are evaluated eagerly.
  • Each chained call returns a new QueryResult.
  • Nodes and relations are stored in memory.
  • Mutating operations (set, remove) modify engine state directly.

Summary

The Query Engine provides:

  • Type-based entry points (engine.query.Type)
  • Chainable filtering and traversal
  • Aggregation and grouping
  • Query composition (union, intersect, exclude)
  • Direct mutation capabilities

It is designed to provide a concise, expressive interface for graph exploration while preserving type constraints enforced by the engine.