Cypher is the most widely use query language for interacting with data in a property graph format. It is structurally and syntactically similar to SQL, with the main difference being the
MATCH clause. The idea of
MATCH is to focus on declaratively describing the graph shape (pattern) that you want and then to let the query compiler pick a good execution plan. What would normally require multiple
JOINs in a relational model often just reduces to one
MATCH with a pattern that has multiple edges:
MATCH (n: Person)-[:has-parent]->(p: Person)-[:lives-in]->(c: City) RETURN p.name AS name, c.name AS parentsCity
Compare the above Cypher to the equivalent SQL below:
SELECT n.name AS name, c.name AS parentsCity FROM persons AS n JOIN persons AS p ON n.parent = p.id JOIN cities AS c ON p.city = c.id
Cypher queries are used in Quine for several purposes:
- Used to ingest events and create the graph
- Set as standing queries to find live matches from the dynamically changing graph
- Entered in the query bar of the Exploration UI
- Set as “quick queries” in the Exploration UI
- Sent directly through the REST API
Interactive railroad diagrams for the Cypher language syntax are a helpful tool. Example:
Almost all of the Cypher language is supported with a few notable exceptions:
- Nodes found in a Cypher
MATCHstatement do not include updates made in the same query following the match statement. Some particular cases where this tends to be more surprising are:
- When updating a node’s labels or properties with
SET n :MyLabel,
SET n.foo = "bar", or
SET n += propertyMap, the
nvariable representing the node will not reflect the update.
- The same node can be aliased under two different names at two different and those two aliases may be different if there have been intervening changes.
- The identity of an edge in Quine is determined entirely by the direction, label, and endpoints of the edge. This has several implications:
- Edges do not have IDs. A query like
MATCH (n)-[e]->(m) RETURN id(e)does not return a useful value. Looking up edges must be done from one of the nodes on either side.
- There cannot be multiple edges with the same label and direction connecting the same two nodes. If a query such as
MATCH (n), (m) WHERE id(n) = idFrom(0) AND id(m) = idFrom(1) CREATE (n)-[:myEdge]->(m)is run twice, the second
CREATEwill have no effect since the single possible edge already exists.
- Properties on edges are not supported. Edges can always be equally represented as an
edge-node-edgeinstead of just an
edge. The node in the middle becomes the carrier for properties that are about the relationship. Quine does not suffer from graph traversal challenges that sometimes motivate users to limit query length, so this node amplification is not problematic in Quine.
- The runtime characteristics of setting a node label are exactly equivalent to using a property. Querying using labels does not enable more efficient scanning, it is just an additional filter condition. Even if there are only a handful of nodes with the
:Personlabel on them, a query such as
MATCH (p:Person) RETURN DISTINCT p.namewill still need to scan all nodes to find those with the desired
DETACH DELETEdoes not work on a path.
allShortestPathscannot be used inside a
MERGEpattern - they can only be used as expressions returning a path, or list of paths.
- Some aggregation functions are not yet implemented:
avgdo not work on durations.
- Hints inside queries (an advanced Cypher feature) are not supported and are silently ignored.
- Cypher commands are not supported (used for system management in other systems).