19 Query anatomy
You build a query with the IQueryOfNodes<TNode, TInclude> builder and run it with Execute():
var result = db.Query<IEvent>() // entry point
.Where(e => e.Status == EventStatus.Published) // filter
.WhereSearch("jazz quartet") // search
.Include(e => e.Venue) // eager loading
.OrderBy(e => e.StartsUtc) // sort
.Page(0, 20) // page
.Execute(); // runThe calls apply in the order you write them, as in LINQ: filter, then sort, then page. Nothing runs
until Execute(), Count() or a single-row helper. Use the builder methods, not LINQ on the
result. The builder's Where runs in the engine against the indexes. LINQ on a result filters
nodes already loaded into your process.
- Queries are immutable — As in LINQ, every operator returns a new query and leaves the original unchanged. You can keep a base query, share it between threads and branch from it:
- Heavy queries, and stopping one — Queries run side by side, and a query that reads many nodes from disk does not hold up writes. A query sees the database as it was when it started. To stop a query, give its context a cancellation token. The query throws…
- Entry points — Query<T>() matches every node of type T and of its subtypes; narrow it with WhereTypes. QueryType is for tooling that has only a type name or id.
- Executing — TryGet is the safe way to read something you expect at most once.