-
Notifications
You must be signed in to change notification settings - Fork 276
Neo4j::Cypher Match
Pattern matching is one of the pillars of Cypher. The pattern is used to describe the shape of the data that we are looking for. Cypher will then try to find patterns in the graph — these are called matching sub graphs. See the Neo4j Documenation on Match
The neo4j-cypher DSL uses the folloing matching methods/operators: <
, >
, >>
, <<
, <=>
and both
, outgoing
and incoming
methods.
The <<
, <=>
and >>
is used when you don't care what type of relationship the has.
The other operators and method allows you to specify which relationship(s) to navigate.
Before reading this page please read about how to specify relationship patterns, nodes and variables here: Neo4j::Cypher-Start See Neo4j::Cypher-Return how to specify which value or values should be returned from a match.
The method <=>
will generate a pattern match without regard to type or direction.
Example:
node(3) <=> :x
Generates the following strings: START v1=node(3) MATCH v2 = (v1)--(x) RETURN v2
You can specify the direction of a relationship to match. Example: match all outgoing relationship of any type
node(3, 4) >> :x
See below for the outgoing
method, which works in a similar way (it returns the node instead of the path).
This will generate: START v1=node(3,4) MATCH v2 = (v1)-->(x) RETURN v2
Example: match all incoming relationship of any type and return those incoming nodes:
node(3, 4) << node.ret
This will generate: START v1=node(3,4) MATCH (v1)<--(v2) RETURN v2
See below for the incoming
method, which works in a similar way (it returns the node instead of the path).
If you don't want to specify the direction of the relationship but only the type of relationship
you can use the -
operator:
node(3) - ':knows|friends' - :foo
:foo
# Same as "START n0=node(3) MATCH (n0)-[:knows|friends]-(foo) RETURN foo"
Example, find all incoming relationship of type friends
to a node and return the end node.
node(3) > :friends > node(:x).ret
Will generate: START v1=node(3) MATCH (v1)-[:
friends]->(x) RETURN x
Example, find all incoming relationship of type friends
to a node and return the path.
node(3) < rel(':friends') < node
Will generate: START v1=node(3) MATCH v3 = (v1)<-[:friends]-(v2) RETURN v3
The outgoing
, incoming
and both
method works a bit similar to the <<
, >>
, <=>
operators.
Instead of returning the path it will return the last node.
Example:
node(3).both # same as node(3).both(rel)
This will generate the following string START v1=node(3) MATCH (v1)-[?]-(v2) RETURN v2
The outgoing, incoming and both methods also excepts rel
object(s), string(s) or symbol(s).
Example, only navigate an outgoing relationship of a specific type:
node(2).outgoing(:friends)
Same as START v1=node(2) MATCH (v1)-[:
friends]->(v2) RETURN v2
Notice, unlike the >>
operator the return value is the v2
node.
The same match can also be expressed using the rel
method, example:
node(3).outgoing(rel(:friends))
Here are different ways of writing a DSL for navigating several outgoing relationship types.
node(3).outgoing(rel(:friends, :work, :family))
Generates 'START v1=node(3) MATCH (v1)-[:friends
|work
|family
]->(v2) RETURN v2'
Or
node(3).outgoing(rel(:friends), rel(:work), rel(:friends))
Or
node(3).outgoing(:friends, :work, :family)
The depth of the match be specified in the rel
method.
Example, returns the relationships, if there is a path between 1 and 3 relationships away.
node(3).outgoing('r:KNOWS*1..3')
:r
This generates: START v1=node(3) MATCH (v1)-[r:KNOWS*1..3]->(v2) RETURN r
Similar to:
node(3) > rel(':KNOWS*1..3').ret > :someone
Which generates: START v2=node(3) MATCH (v2)-[v1:KNOWS*1..3]->(someone) RETURN v1
You can combine the outgoing
, incoming
and both
methods to navigate several relationships in one go.
node(3).outgoing(:friends).incoming(:friends).outgoing(:place)
This generates the following: START v1=node(3) MATCH (v1)-[:
friends]->(v2),(v2)<-[:
friends]-(v3),(v3)-[:
place]->(v4) RETURN v4
All start nodes and node variables has a match
, which allows you use a another ruby block for the match expression.
This can be used to avoid using variables and instead rely on method chaining.
Example:
node(3,4).match{|n| n <=> node(5) }
Same as START v1=node(3,4),v2=node(5) MATCH (v1)--(v2) RETURN v1
A more complex example (but silly):
node(3,4).match{|n| n >> :friends} >> :work
Same as 'START v1=node(3,4) MATCH (v1)-->(friends),v2 = (v1)-->(work) RETURN v2`
It is often useful to assign a variable to a paths, relationships or nodes. By doing that you can use the variable as a condition in the WHERE clause or in the RETURN clause.
You can do that in two ways.
Since we have access to the full ruby language we can also use ruby variables (of course).
Example: return all outgoing nodes with property name equal 'andreas'
x = node
node(3) >> x
x[:name] == 'andreas'
x
In the example above a new cypher variable name will automatically be created and used as a normal Ruby variable (x
)
This example will instead create a cypher node variable x
node(3) >> node(:x)
node(:x)[:name] == 'andreas'
:x
Same as START v1=node(3) MATCH (v1)-->(x) WHERE x.name = "andreas" RETURN x
Another example:
node(3).outgoing(:friends).as(:a).incoming(:friends).as(:b).outgoing(:place).as(:c)
Same as START v1=node(3) MATCH (v1)-[:
friends]->(a),(a)<-[:
friends]-(b),(b)-[:
place`]->(c) RETURN c'
A cypher path is return when using the operators like <<
.
The path object has the following useful methods:
-
where
, example:(node(1) << :person).where{|path| path.nodes.all? { |x| x[:age] > 30 }}.ret(:person)
where_not
ret
all?
-
extract
, example(node(1) >> :b >> :c).nodes.extract{ |n| n[:age]}
any?
none?
single?
-
foreach
, example: `(node(2) > rel > node(1)).nodes.foreach {|n| n[:marked] = true} shortest_path
shortest_paths
length
TODO - more docs
The length of a path can be returned, example:
(node(3) >> :b).length
This is same as START v1=node(3) MATCH v2 = (v1)-->(b) RETURN length(v2)
A more complex example
ret(:a, :b, :c, (node(3).as(:a) > ':KNOWS*0..1' > :b).length, (node(:b) > ':BLOCKS*0..1' > :c).length)
Is same as START a=node(3) MATCH v1 = (a)-[:KNOWS*0..1]->(b),v2 = (b)-[:BLOCKS*0..1]->(c) RETURN a,b,c,length(v1),length(v2)
WARNING: Much of the information in this wiki is out of date. We are in the process of moving things to readthedocs
- Project Introduction
- Neo4j::ActiveNode
- Neo4j::ActiveRel
- Search and Scope
- Validation, Uniqueness, and Case Sensitivity
- Indexing VS Legacy Indexing
- Optimized Methods
- Inheritance
- Core: Nodes & Rels
- Introduction
- Persistence
- Find : Lucene
- Relationships
- Third Party Gems & extensions
- Scaffolding & Generators
- HA Cluster