Graph patterns¶
Graph pattern matching is the process of matching a list of regular expressions, which are specifically defined by the GQL standard, against a property graph to get a set of reduced matches.
A graph pattern is a list of path patterns, which are in turn lists of interleaving node patterns and edge patterns. A path pattern always starts and ends with nodes. The following is an example of a path pattern containing two node patterns (i.e., aliased as a and b, respectively) connected by an edge pattern (i.e., aliased as e and labeled as KNOWS). In the node pattern for a, a filter condition WHERE is declared on the property id.
(a:Person WHERE a.id IN LIST[2, 3, 4, 888])-[e:KNOWS]->(b)
In GQL, we define the term path as walk from the graph theory, where a node or edge may appear multiple times in a path. If you need to find a path with distinct nodes and edges, you can declare patterns with filter conditions to rule out duplicate nodes and edges.
For more information, see the following topics:
Label expressions vs. type specifications¶
In GQL patterns, there are two common ways to narrow graph elements:
- Label expressions use the
:orISprefix to filter by label. - Type specifications use the
@prefix to filter by node type or edge type.
The key difference is:
- A type is a structural definition in the graph type. It determines the property set, primary keys, and for edges, source and destination constraints.
- A label is a semantic classification of graph elements. The same label can be reused by multiple types.
As a result, type-based queries are usually more precise and are better when you want to target one specific structure. Label-based queries are usually more flexible and are better when you want to filter across multiple types by shared semantics.
Label expressions¶
Label expressions support the | (or), & (and), and ! (not) operators. For example:
(v:Person|Movie)matches nodes labeledPersonorMovie.(v:Person&Movie)matches nodes labeled bothPersonandMovie.[e:!Act]matches edges not labeledAct.
Note that labels use different syntax in different contexts:
- In a pattern filler, the label expression appears directly after the variable and uses
:orIS, for example(v:Person)or(v IS Person). - In a WHERE clause, label matching uses a labeled predicate. The full form is
v IS LABELED Person. For example:MATCH (v)-[e]->() WHERE v IS LABELED Person RETURN v.
In a WHERE clause, you can also use a colon (:) as a shorthand for IS LABELED, for example WHERE e:Act. For more information, see Labeled predicate.
Type specifications¶
Type specifications support listing multiple types with @[Type1, Type2]. For example:
(v@[Actor,Director])matches nodes of typeActororDirector.[e@[Watch,Direct]]matches edges of typeWatchorDirect.
Difference in result scope¶
Using the example dataset as an example, the node types Actor, Director, and User all use the Person label. Therefore:
MATCH (v@Actor)matches onlyActornodes.MATCH (v:Person)matches all nodes labeledPerson, includingActor,Director, andUser.
The same idea applies to edge patterns. If multiple edge types reuse the same label, then:
MATCH ()-[e@Click]->()matches only theClickedge type.MATCH ()-[e:Behavior]->()matches all edges labeledBehavior.
When to use each¶
- Use
@type_namewhen you need precise matching by structural type in the schema. - Use
:labelorIS LABELEDwhen you need cross-type filtering by semantic label.
Both approaches filter in the pattern and enable the optimizer to use indexes. Avoid filtering types in WHERE clauses, such as WHERE type(e) IN [...], because this is usually less efficient.
For more information, see Label expressions, Node patterns, and Edge patterns.