Relatude Help

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();                                      // run

The 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.