Cypher Patterns

Using patterns in Cypher, you can describe the shape of the data you’re looking for. Patterns appear in multiple places in Cypher language syntax, such as in MATCH, CREATE, MERGE, and WHERE clauses. This section describes AnzoGraph compatibility with Cypher pattern features based on the Cypher Query Language Reference specification:

Uniqueness (Not Supported)

While pattern matching, Cypher makes sure that it does not include matches where the same graph relationship is found multiple times in a single pattern. Cypher specifies the relationship isomorphism, that is, the relationship is not repeated in a single path matching the pattern.

AnzoGraph's implementation of Cypher currently does not support relationship uniqueness. Thus, it may allow the same relationship to appear multiple times within the matched path. For example, take the following CREATE statement and the subsequent query:

CREATE (adam:User {name: 'Adam'}), (pernilla:User {name: 'Pernilla'}),
(david:User {name: 'David'}),
(adam)-[:FRIEND]->(pernilla), (pernilla)-[:FRIEND]->(david);
MATCH (user:User {name: 'Adam'})-[r1:FRIEND]-()-[r2:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName;

With uniqueness enforced, the expected result might be the following:

+---------+
| fofName |
+---------+
| "David" |
+---------+
1 row

In AnzoGraph, the same query could return the following result:

fofName
"Adam"
"David"
2 rows

Patterns for Nodes (Supported)

A node in a pattern is simply described using a pair of parentheses, and they are typically given a name. For example:

(a)

In this example, the pattern describes a single node, and the node is named using the variable a.

Patterns for Related Nodes (Supported)

Cypher patterns describe relationships by specifying an arrow between two nodes. For

example:

(a)-[]->(b)

This pattern describes a very simple data shape, that is, two nodes and a single relationship from one to the other. In this example, the two nodes are named a and b respectively and the relationship is "directed", as it goes from a to b.

Patterns for Labels (Supported)

In addition to describing the shape of a node in the pattern, you can also describe its attributes. The simplest attribute that can be described in the pattern is a label that the node must have.

For example:

(a:User)-[]->(b)

You can also specify a node that has multiple labels. For example:

(a:User:Admin)-[]->(b)

Specifying Properties (Supported)

Nodes and relationships are the fundamental structures in a graph. Cypher allows the use of properties on both of these to let users express far richer models. Properties can be expressed in patterns using a map construct, that is, curly brackets ( { } ) surrounding a number of key-expression pairs, separated by commas. For example, a node with two properties would look like:

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

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.

Patterns for Relationships (Supported)

As described earlier, the simplest way to describe a relationship is by specifying an arrow between two nodes. That way, you can describe that the relationship should exist and also specify its direction. If you do not care about the direction of the relationship, you can omit the arrow head. For example:

(a)-[]-(b)

As with nodes, relationships may also be given names. In that case, you can insert a pair of square brackets to break up the arrow and specify the variable label within the square brackets. For example:

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

Similar to labels on nodes, relationships can also have types. To describe a relationship with a specific type, you can specify the type following the variable name. For example:

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

Unlike labels, relationships can only have one type. However, if a relationship could be one of a set of different types, you can list them all in the pattern, separated by the pipe symbol ( | ), that is:

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

Keep in mind that these forms of patterns can only be used to describe existing data (that is, when using a pattern with the MATCH clause, or as an expression).

Also note that, as with nodes, the name of the relationship can always be omitted. For example:

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

Variable-length Pattern Matching (Partially Supported)

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

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

A range of lengths can also be specified. Such relationship patterns are called "variable-length relationships". For example:

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

The openCypher specification allows several variations in its syntax to specify the length of a relationship path. For example, you can omit either the minimum or maximum relationship path length, or even omit both.

Currently, AnzoGraph supports only a few variations of Cypher variable length pattern matching. AnzoGraph restrictions are the following:

  1. Variable length patterns must include the relationship type. For example:
    (a)-[:KNOWS*]->(b)
  2. Only Zero Or More and One Or More path patterns are supported. For example:
    (a)-[:KNOWS*]->(b), (a)-[:KNOWS*1]->(b)
  3. Edge variable projection is not supported, since the list type is not yet supported. For example:
    (a)-[r:KNOWS*]->(b)

Assigning to Path Variables (Not Supported)

A series of connected nodes and relationships is called a "path". The Cypher specification allows paths to be named using an identifier. For example:

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

The current AnzoGraph release does not support naming paths.

Related Topics