Reputation: 6364
How to create all edges that using one statement in Cypher?
For example: lets say I have one object like this
Employees {name: "abc, country: "NZ", zipcode: "123456"}
Employees {name: "def", country: "AUS", zipcode: "964573"}
and lets say I have the following Manager objects
Manager { name: "abc", depatment: "product"}
Manager {name: "abc", depatment: "sales"}
Manager {name: "abc", depatment: "marketing"}
and Finally the Address Objects
Address {zipcode: "964573", street: "Auckland St"}
Now I want to create all the edges where Employees.name = Manager.name and Employees.zipcode = Address.zipcode
however if Employees.name != Manager.name
but Employees.zipcode = Address.zipcode
then I want all the edges to be created between Employees
and Address
similarly if Employees.zipcode != Address.zipcode
but Employees.name = Manager.name
then I want all the edges to be created between Employees
and Manager
. And I want to achieve all of this in one single statement/query
Simply put if there are matching vertices between Employees, Manager and Address I want all the edges to be created between them but if there only a match between any two I want the edge to be created between those two vertices as well. And I am trying to all of this in a single query/statement?
Is this possible to write a query in one statement that can satisfy all the conditions above?
What I tried so far is this
Find the pairs first with MATCH clause and then CREATE a relationship between them.
MATCH (e:Employees),(m:Manager), (a:Address)
WHERE e.name=m.name or e.zipcode = a.zipcode
WITH e,m,a
CREATE (m)-[:REL_NAME]->(e), (e)-[:ADDR_REL]->(a)
This clearly won't work because of the Where
clause because if e.name=m.name
then e.zipcode = a.zipcode
won't be checked and therefore no edge will be created between employees and address.
Upvotes: 0
Views: 222
Reputation: 67019
The following query avoids producing a cartesian product of all 3 node labels (and will perform better if you have indexes for :Manager(name)
and :Address(zipcode)
):
MATCH (e:Employees)
OPTIONAL MATCH (m:Manager)
WHERE e.name = m.name
WITH e, COLLECT(m) AS mList
FOREACH(x IN mList | CREATE (x)-[:REL_NAME]->(e))
WITH e
OPTIONAL MATCH (a:Address)
WHERE e.zipcode = a.zipcode
WITH e, COLLECT(a) AS aList
FOREACH(y IN aList | CREATE (e)-[:ADDR_REL]->(y))
Upvotes: 1