user2720919
user2720919

Reputation: 27

Cypher query using foreach

I am trying to make relationships between users with same pincode. My data looks like below:

User Pincodes
A [111,222]
B [111,333]
C [333,444]
D [111,222]

So, I want to create relationships between A and B as they have same pincode and another relationship between B an C. I wrote something like below, that is absolutely not what I want.

MATCH (a:User),(b:User)
WHERE a.pincode=b.pincode
WITH COLLECT([a,b]) AS its
FOREACH (pincode IN its |
    CREATE (a)-[r:LIVESINSAMEAREAAS]->(b)
);

Upvotes: 1

Views: 9748

Answers (2)

Bruno Peres
Bruno Peres

Reputation: 16355

EDIT:

From the comments:

I have added one new record in my question(please see above). Now if I use your query, it will create a relationship between A, B and D. There is another common pincode between A and D and this is getting included in the previous relationship itself. Can we update your query such that the two different realationships are included?

This query using filter and FOREACH should work:

MATCH (a:User),(b:User)
WHERE id(a) > id(b)
WITH a, b, filter(ap in a.pincodes where ap in b.pincodes) as pincodes
FOREACH (pc in pincodes | CREATE (a)-[:LIVESINSAMEAREAAS]->(b))

ORIGINAL ANSWER:

I'm assuming that pincode is a list of integers. So I created this sample data based on your question:

create (:User {pincodes : [111,222]}) 
create (:User {pincodes : [111,333]}) 
create (:User {pincodes : [333,444]})

I wrote a query to get all nodes that have at least one in common pincode. Then a relationship :LIVESINSAMEAREAAS is created between these nodes.

MATCH (a:User),(b:User)
WHERE id(a) > id(b) AND ANY (ap in a.pincodes WHERE ap IN b.pincodes)
CREATE (a)-[r:LIVESINSAMEAREAAS]->(b)

The first condition in the WHERE (id(a) > id(b)) is used to avoid a cartesian product and the creation of the relationship in both directions. That is: (a)-->(b) and (b)-->(a).

In the second condition I'm filtering pair of nodes that at least one pincode of a is contained in the list of pincodes of b.

Upvotes: 1

stdob--
stdob--

Reputation: 29172

Although the solution from @Bruno Peres works, it will be reasonable to follow the spirit of the graphs, and make the area a separate node. For example:

MATCH (U:User) UNWIND U.pincodes as pincode
MERGE (A:Area {pincode: pincode})
MERGE (U)-[:liveInTheArea]->(A)
RETURN *

Upvotes: 1

Related Questions