Fixed length patterns
The most basic form of graph pattern matching in Cypher® involves the matching of fixed length patterns. This includes node patterns, relationship patterns, and path patterns.
Node patterns
Every graph pattern contains at least one node pattern. The simplest graph pattern is a single, empty node pattern:
MATCH ()
The empty node pattern matches every node in a property graph. In order to obtain a reference to the nodes matched, a variable needs to be declared in the node pattern:
MATCH (n)
With this reference, node properties can be accessed:
MATCH (n)
RETURN n.name
Adding a label expression to the node pattern means only nodes with labels that match will be returned.
The following matches nodes that have the Stop
label:
MATCH (n:Stop)
The following more complex label expression matches all nodes that are either a TrainStation
and a BusStation
or StationGroup
:
MATCH (n:(TrainStation&BusStation)|StationGroup)
A map of property names and values can be used to match on node properties based on equality with the specified values.
The following matches nodes that have their mode
property equal to Rail
:
MATCH (n { mode: 'Rail' })
More general predicates can be expressed with a WHERE
clause.
The following matches nodes whose name property starts with Preston
:
MATCH (n:Station WHERE n.name STARTS WITH 'Preston')
RETURN n
See the node patterns reference section for more details.
Relationship patterns
The simplest possible relationship pattern is a pair of dashes:
--
This pattern matches a relationship with any direction and does not filter on any relationship type or property.
Unlike a node pattern, a relationship pattern cannot be used in a MATCH
clause without node patterns at both ends.
See path patterns for more details.
In order to obtain a reference to the relationships matched by the pattern, a relationship variable needs to be declared in the pattern by adding the variable name in square brackets in between the dashes:
-[r]-
To match a specific direction, add <
or >
to the left or right hand side respectively:
-[r]->
To match on a relationship type, add the type name after a colon:
-[:CALLS_AT]->
Similar to node patterns, a map of property names and values can be added to filter on properties of the relationship based on equality with the specified values:
-[{ distance: 0.24, duration: 'PT4M' }]->
A WHERE
clause can be used for more general predicates:
-[r WHERE time() + duration(r.duration) < time('22:00') ]->
See the relationship patterns reference section for more details.
Path patterns
Any valid path starts and ends with a node, with relationships between each node (if there is more than one node). Fixed length path patterns have the same restrictions, and for all valid path patterns the following are true:
-
They have at least one node pattern.
-
They begin and end with a node pattern.
-
They alternate between nodes and relationships.
These are all valid path patterns:
()
(s)--(e)
(:Station)--()<--(m WHERE m.departs > time('12:00'))-->()-[:NEXT]->(n)
These are invalid path patterns:
-->
()-->
()-->-->()
Path pattern matching
This section contains an example of matching a path pattern to paths in a property graph.
It uses the following graph:
To recreate the graph, run the following query against an empty Neo4j database:
CREATE (pmr:Station {name: 'Peckham Rye'}),
(dmk:Station {name: 'Denmark Hill'}),
(vic:Station {name: 'London Victoria'}),
(clp:Station {name: 'Clapham High Street'}),
(eph:Station {name: 'Elephant & Castle'}),
(vic)<-[:CALLS_AT]-(s1:Stop {departs: time('11:55')}),
(dmk)<-[:CALLS_AT]-(s2:Stop {departs: time('11:44')})-[:NEXT]->(s1),
(pmr)<-[:CALLS_AT]-(s3:Stop {departs: time('11:40')})-[:NEXT]->(s2),
(clp)<-[:CALLS_AT]-(s4:Stop {departs: time('11:41')}),
(dmk)<-[:CALLS_AT]-(s5:Stop {departs: time('11:37')})-[:NEXT]->(s4),
(pmr)<-[:CALLS_AT]-(s6:Stop {departs: time('11:33')})-[:NEXT]->(s5),
(eph)<-[:CALLS_AT]-(s7:Stop {departs: time('11:54')}),
(dmk)<-[:CALLS_AT]-(s8:Stop {departs: time('11:47')})-[:NEXT]->(s7),
(pmr)<-[:CALLS_AT]-(s9:Stop {departs: time('11:44')})-[:NEXT]->(s8)
The graph contains a number of train Stations
and Stops
.
A Stop
represents the arrival and departure of a train that CALLS_AT
a Station
.
Each Stop
forms part of a sequence of Stops
connected by relationships with the type NEXT
, representing the order of calling points made by a train service.
The graph shows three chains of Stops
that represent different train services.
Each of these services calls at the Station
with the name Denmark Hill
.
To return all Stops
that call at the Station
Denmark Hill
, the following motif is used (the term motif is used to describe the pattern looked for in the graph):
In this case, three paths in the graph match the structure of the motif (plus the predicate anchoring to the Station
Denmark Hill
):
In order to return the name of each Stop
that calls at a Station
, declare a variable in the Stop
node pattern.
The results will then have a row containing the departs value of each Stop
for each match shown above:
MATCH (s:Stop)-[:CALLS_AT]->(:Station {name: 'Denmark Hill'})
RETURN s.departs AS departureTime
departureTime |
---|
|
|
|
Rows: 3 |