# Graph Query Language

The Curiosity Graph Query Language is a fluent interface used to interact with the graph database. It is primarily accessed via the Q() helper method in Custom Endpoints or through the IQuery interface in Data Connectors (with a reduced feature set).

# Overview

The query language follows a pipeline approach:

  1. Start: Define the starting set of nodes (e.g., all nodes of a type, a specific search, or a list of UIDs).
  2. Filter: Narrow down the set based on properties, relationships, or permissions.
  3. Traverse: Move from the current set of nodes to related nodes (e.g., "get authors of these books").
  4. Project/Sort: Define what data to return and in what order.
  5. Execute: Materialize the results (e.g., as a list, count, or JSON).

# Starting Points

Every query must start by defining an initial set of nodes.

Method Description Example
StartAt(string nodeType) Starts with all nodes of a specific type. Q().StartAt("Person")
StartAt(UID128 uid) Starts with a specific node by UID. Q().StartAt(uid)
StartSearch(string nodeType, string field, ISearchExpression query) Starts with a full-text search. Q().StartSearch("Document", "Content", Search("keyword"))
StartWhere(string nodeType, string field, Func<dynamic, bool> predicate) Starts by filtering on a specific field. Q().StartWhere("Product", "Price", p => p > 100)
StartAtSimilarText(string text, ...) Starts with nodes similar to the input text. Q().StartAtSimilarText("machine learning")
StartNearTo(...) Starts with nodes near a geographical location. Q().StartNearTo("Store", "Location", myGeoPoint, 1000)

# Examples

// Start with all "Project" nodes
var projects = Q().StartAt("Project");

// Start with a specific search
var results = Q().StartSearch("Email", "Subject", Search("urgent"));

# Filtering

Refine the current set of nodes.

Method Description Example
Where(Func<ReadOnlyNode, bool> predicate) Filters nodes using a lambda expression. Q().Where(n => n.Score > 0.5)
Where(string field, Func<dynamic, bool> predicate) Filters based on a dynamic field value. Q().Where("Age", a => a > 18)
WhereString(string field, string value) Optimized filter for string equality. Q().WhereString("Status", "Active")
WhereTimestamp(Time from, Time to, bool inside) Filters nodes by creation/modification time. Q().WhereTimestamp(DateTime.Now.AddDays(-1), DateTime.Now, true)
ExceptType(string type) Removes nodes of a specific type. Q().ExceptType("Confidential")
IsRelatedTo(UID128 uid) Keeps nodes related to a specific UID. Q().IsRelatedTo(userUid)
IsNotRelatedTo(string type) Removes nodes related to a specific type. Q().IsNotRelatedTo("Deprecated")

# Examples

// Filter active users
Q().StartAt("User")
   .WhereString("Status", "Active");

// Filter documents created in the last 7 days
Q().StartAt("Document")
   .WhereTimestamp(DateTime.Now.AddDays(-7), DateTime.Now, true);

# Graph Traversal

Move from the current nodes to their neighbors.

Method Description Example
Out(string nodeType, string edgeType) Traverses to connected nodes. Q().Out("Author", "HasAuthor")
OutMany(int levels, ...) Traverses multiple hops deep. Q().OutMany(2, new[]{"Friend"})
PathBetween(UID128 from, UID128 to) Finds paths between two nodes. Q().PathBetween(startUid, endUid)

# Examples

// Get all authors of books matching "Graph DB"
Q().StartSearch("Book", "Title", Search("Graph DB"))
   .Out("Author", "WrittenBy");

// Get friends of friends
Q().StartAt(currentUserUid)
   .OutMany(2, new[] { "Person" }, new[] { "FriendOf" });

# Output and Projection

Define what extra information to include in the result.

Method Description Example
Emit(string name, ...) Includes a field or object in the output. Q().Emit("Details")
EmitWithEdges(string name) Includes edge information. Q().EmitWithEdges("Relationships")
EmitCount(string name) Includes the count of results. Q().EmitCount("TotalCount")
EmitSummary(string name) Includes a summary of the results. Q().EmitSummary("Overview")

# Examples

// Return books with their author edges
Q().StartAt("Book")
   .EmitWithEdges(null, false, "WrittenBy");

# Sorting and Pagination

Control the order and number of results.

Method Description Example
SortByTimestamp(bool oldestFirst) Sorts by creation time. Q().SortByTimestamp(false)
SortByLastUpdated(bool newestFirst) Sorts by last modification time. Q().SortByLastUpdated(true)
SortByConnectivity() Sorts by number of connections. Q().SortByConnectivity()
Skip(int count) Skips the first N results. Q().Skip(10)
Take(int count) Limits the result to N items. Q().Take(20)

# Examples

// Get top 10 most recent documents
Q().StartAt("Document")
   .SortByTimestamp(false)
   .Take(10);

# Execution

Materialize the query execution into a result.

Method Description Example
ToList() Executes and returns a List<ReadOnlyNode>. var list = query.ToList();
Count() Returns the number of results. int count = query.Count();
Any() Returns true if there are any results. bool exists = query.Any();
ToJsonAsync() Serializes results to a JSON string. string json = await query.ToJsonAsync();

# Examples

// Get count of users
int count = Q().StartAt("User").Count();

// Get list of high-priority tasks
var tasks = Q().StartAt("Task")
               .WhereString("Priority", "High")
               .ToList();