## 9.6. Patterns

Patterns and pattern-matching are at the very heart of Cypher, so being effective with Cypher requires a good understanding of patterns.

Using patterns, you describe the shape of the data you’re looking for. For example, in the `MATCH` clause you describe the shape with a pattern, and Cypher will figure out how to get that data for you.

The pattern describes the data using a form that is very similar to how one typically draws the shape of property graph data on a whiteboard: usually as circles (representing nodes) and arrows between them to represent relationships.

Patterns appear in multiple places in Cypher: in `MATCH`, `CREATE` and `MERGE` clauses, and in pattern expressions. Each of these is described in more details in:

### Patterns for nodes

The very simplest “shape” that can be described in a pattern is a node. A node is described using a pair of parentheses, and is typically given a name. For example:

`(a)`

This simple pattern describes a single node, and names that node using the variable `a`.

### Labels

In addition to simply describing the shape of a node in the pattern, one can also describe attributes. The most simple attribute that can be described in the pattern is a label that the node must have. For example:

`(a:User)-->(b)`

One can also describe a node that has multiple labels:

`(a:User:Admin)-->(b)`

### Specifying properties

Nodes and relationships are the fundamental structures in a graph. Neo4j uses properties on both of these to allow for far richer models.

Properties can be expressed in patterns using a map-construct: curly brackets surrounding a number of key-expression pairs, separated by commas. E.g. a node with two properties on it would look like:

`(a { name: "Andres", sport: "Brazilian Ju-Jitsu" })`

A relationship with expectations on it would could look like:

`(a)-[{blocked: false}]->(b)`

When properties appear in patterns, they add an additional constraint to the shape of the data. In the case of a `CREATE` clause, the properties will be set in the newly created nodes and relationships. In the case of a `MERGE` clause, the properties will be used as additional constraints on the shape any existing data must have (the specified properties must exactly match any existing data in the graph). If no matching data is found, then `MERGE` behaves like `CREATE` and the properties will be set in the newly created nodes and relationships.

Note that patterns supplied to `CREATE` may use a single parameter to specify properties, e.g: `CREATE (node {paramName})`. This is not possible with patterns used in other clauses, as Cypher needs to know the property names at the time the query is compiled, so that matching can be done effectively.

### Describing relationships

The simplest way to describe a relationship is by using the arrow between two nodes, as in the previous examples. Using this technique, you can describe that the relationship should exist and the directionality of it. If you don’t care about the direction of the relationship, the arrow head can be omitted, like so:

`(a)--(b)`

As with nodes, relationships may also be given names. In this case, a pair of square brackets is used to break up the arrow and the variable is placed between. For example:

`(a)-[r]->(b)`

Much like labels on nodes, relationships can have types. To describe a relationship with a specific type, you can specify this like so:

`(a)-[r:REL_TYPE]->(b)`

Unlike labels, relationships can only have one type. But if we’d like to describe some data such that the relationship could have any one of a set of types, then they can all be listed in the pattern, separating them with the pipe symbol `|` like this:

`(a)-[r:TYPE1|TYPE2]->(b)`

Note that this form of pattern can only be used to describe existing data (ie. when using a pattern with `MATCH` or as an expression). It will not work with `CREATE` or `MERGE`, since it’s not possible to create a relationship with multiple types.

As with nodes, the name of the relationship can always be omitted, in this case like so:

`(a)-[:REL_TYPE]->(b)`

#### Variable length

 CautionVariable length pattern matching in versions 2.1.x and earlier does not enforce relationship uniqueness for patterns described inside of a single `MATCH` clause. This means that a query such as the following: `MATCH (a)-[r]->(b), (a)-[rs*]->(c) RETURN *` may include `r` as part of the `rs` set. This behavior has changed in versions 2.2.0 and later, in such a way that `r` will be excluded from the result set, as this better adheres to the rules of relationship uniqueness as documented here Section 8.4, “Uniqueness”. If you have a query pattern that needs to retrace relationships rather than ignoring them as the relationship uniqueness rules normally dictate, you can accomplish this using multiple match clauses, as follows: `MATCH (a)-[r]->(b) MATCH (a)-[rs*]->(c) RETURN *`. This will work in all versions of Neo4j that support the `MATCH` clause, namely 2.0.0 and later.

Rather than describing a long path using a sequence of many node and relationship descriptions in a pattern, many relationships (and the intermediate nodes) can be described by specifying a length in the relationship description of a pattern. For example:

`(a)-[*2]->(b)`

This describes a graph of three nodes and two relationship, all in one path (a path of length 2). This is equivalent to:

`(a)-->()-->(b)`

A range of lengths can also be specified: such relationship patterns are called “variable length relationships”. For example:

`(a)-[*3..5]->(b)`

This is a minimum length of 3, and a maximum of 5. It describes a graph of either 4 nodes and 3 relationships, 5 nodes and 4 relationships or 6 nodes and 5 relationships, all connected together in a single path.

Either bound can be omitted. For example, to describe paths of length 3 or more, use:

`(a)-[*3..]->(b)`

And to describe paths of length 5 or less, use:

`(a)-[*..5]->(b)`

Both bounds can be omitted, allowing paths of any length to be described:

`(a)-[*]->(b)`

As a simple example, let’s take the query below:

Query

```MATCH (me)-[:KNOWS*1..2]-(remote_friend)
WHERE me.name = "Filipa"
RETURN remote_friend.name```

Result

remote_friend.name
2 rows

`"Dilshad"`

`"Anders"`

Try this query live create (_0 {`name`:"Anders"}) create (_1 {`name`:"Becky"}) create (_2 {`name`:"Cesar"}) create (_3 {`name`:"Dilshad"}) create (_4 {`name`:"Emil"}) create (_5 {`name`:"Filipa"}) create (_0)-[:`KNOWS`]->(_3) create (_0)-[:`KNOWS`]->(_2) create (_0)-[:`KNOWS`]->(_1) create (_1)-[:`KNOWS`]->(_4) create (_2)-[:`KNOWS`]->(_4) create (_3)-[:`KNOWS`]->(_5) MATCH (me)-[:KNOWS*1..2]-(remote_friend) WHERE me.name = "Filipa" RETURN remote_friend.name

This query finds data in the graph which a shape that fits the pattern: specifically a node (with the name property `Filipa`) and then the `KNOWS` related nodes, one or two steps out. This is a typical example of finding first and second degree friends.

Note that variable length relationships can not be used with `CREATE` and `MERGE`.

### Assigning to path variables

As described above, a series of connected nodes and relationships is called a "path". Cypher allows paths to be named using an identifer, like so:

`p = (a)-[*3..5]->(b)`

You can do this in `MATCH`, `CREATE` and `MERGE`, but not when using patterns as expressions.