Skip to content
Developer Edition runs on one host and does not require a product license file. Need multi-host deployment or performance testing at scale? Explore Enterprise Edition

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 : or IS prefix 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 labeled Person or Movie.
  • (v:Person&Movie) matches nodes labeled both Person and Movie.
  • [e:!Act] matches edges not labeled Act.

Note that labels use different syntax in different contexts:

  • In a pattern filler, the label expression appears directly after the variable and uses : or IS, 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 type Actor or Director.
  • [e@[Watch,Direct]] matches edges of type Watch or Direct.

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 only Actor nodes.
  • MATCH (v:Person) matches all nodes labeled Person, including Actor, Director, and User.

The same idea applies to edge patterns. If multiple edge types reuse the same label, then:

  • MATCH ()-[e@Click]->() matches only the Click edge type.
  • MATCH ()-[e:Behavior]->() matches all edges labeled Behavior.

When to use each

  • Use @type_name when you need precise matching by structural type in the schema.
  • Use :label or IS LABELED when 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.