user1870400
user1870400

Reputation: 6364

How to create all edges that using one statement in Cypher?

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.namethen 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

Answers (1)

cybersam
cybersam

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

Related Questions