Patterns
Neo4j’s Property Graphs are composed of nodes and relationships, either of which may have properties. Nodes represent entities, for example concepts, events, places and things. Relationships connect pairs of nodes.
However, nodes and relationships can be considered as low-level building blocks. The real strength of the property graph lies in its ability to encode patterns of connected nodes and relationships. A single node or relationship typically encodes very little information, but a pattern of nodes and relationships can encode arbitrarily complex ideas.
Cypher®, Neo4j’s query language, is strongly based on patterns. Specifically, patterns are used to match desired graph structures. Once a matching structure has been found or created, Neo4j can use it for further processing.
A simple pattern, which has only a single relationship, connects a pair of nodes (or, occasionally, a node to itself).
For example, a Person LIVES_IN
a City or a City is PART_OF
a Country.
Complex patterns, using multiple relationships, can express arbitrarily complex concepts and support a variety of interesting use cases.
For example, we might want to match instances where a Person LIVES_IN
a Country.
The following Cypher code combines two simple patterns into a slightly more complex pattern which performs this match:
(:Person) -[:LIVES_IN]-> (:City) -[:PART_OF]-> (:Country)
Diagrams made up of icons and arrows are commonly used to visualize graphs. Textual annotations provide labels, define properties etc.
Node syntax
Cypher uses a pair of parentheses to represent a node: ()
.
This is reminiscent of a circle or a rectangle with rounded end caps.
Below are some examples of nodes, providing varying types and amounts of detail:
()
(matrix)
(:Movie)
(matrix:Movie)
(matrix:Movie {title: 'The Matrix'})
(matrix:Movie {title: 'The Matrix', released: 1997})
The simplest form, ()
, represents an anonymous, uncharacterized node.
If we want to refer to the node elsewhere, we can add a variable, for example: (matrix)
.
A variable is restricted to a single statement.
It may have different or no meaning in another statement.
The :Movie
pattern declares a label of the node.
This allows us to restricts the pattern, keeping it from matching (say) a structure with an Actor
node in this position.
The node’s properties, for example title
, are represented as a list of key-value pairs, enclosed within a pair of braces, for example: {name: 'Keanu Reeves'}
.
Properties can be used to store information and/or restrict patterns.
Relationship syntax
Cypher uses a pair of dashes (--
) to represent an undirected relationship.
Directed relationships have an arrowhead at one end (<--
, -->
).
Bracketed expressions ([...]
) can be used to add details.
This may include variables, properties, and type information:
-->
-[role]->
-[:ACTED_IN]->
-[role:ACTED_IN]->
-[role:ACTED_IN {roles: ['Neo']}]->
The syntax and semantics found within a relationship’s bracket pair are very similar to those used between a node’s parentheses.
A variable (e.g., role
) can be defined, to be used elsewhere in the statement.
The relationship’s type (e.g., :ACTED_IN
) is analogous to the node’s label.
The properties (e.g., roles
) are entirely equivalent to node properties.
Pattern syntax
Combining the syntax for nodes and relationships, we can express patterns. The following could be a simple pattern (or fact) in this domain:
(keanu:Person:Actor {name: 'Keanu Reeves'})-[role:ACTED_IN {roles: ['Neo']}]->(matrix:Movie {title: 'The Matrix'})
Equivalent to node labels, the :ACTED_IN
pattern declares the relationship type of the relationship.
Variables (e.g., role
) can be used elsewhere in the statement to refer to the relationship.
As with node properties, relationship properties are represented as a list of key/value pairs enclosed within a pair of braces, for example: {roles: ['Neo']}
.
In this case, we used an array property for the roles
, allowing multiple roles to be specified.
Properties can be used to store information and/or restrict patterns.
Pattern variables
To increase modularity and reduce repetition, Cypher allows patterns to be assigned to variables. This allows the matching paths to be inspected, used in other expressions, etc.
acted_in = (:Person)-[:ACTED_IN]->(:Movie)
The acted_in
variable would contain two nodes and the connecting relationship for each path that was found or created.
There are a number of functions to access details of a path, for example: nodes(path)
, relationships(path)
, and length(path)
.
Clauses
Cypher statements typically have multiple clauses, each of which performs a specific task, for example:
-
create and match patterns in the graph
-
filter, project, sort, or paginate results
-
compose partial statements
By combining Cypher clauses, we can compose more complex statements that express what we want to know or create.
Was this page helpful?