0

What I am trying to get to

I am trying to get nodes of outgoing relationships in separate columns. The resulting data should look like the following:

node1 nodeRel1 nodeRel2
{...} [{...}, {...}, ...] [{...}, {...}, ...]
{...} [{...}, {...}, ...] [{...}, {...}, ...]

Where node1 is the starting node with label Label1, nodeRel1 are all the nodes connected to node1 through REL1 with label Label2, and nodeRel2 are all the nodes connected to node1 through REL2 with label Label3.
EDIT:
To specify, this is quite doable with two relationships like so (as pointed out by @nimrod serok): MATCH ()-[]-(origin)-[]-(), but this only works with two relationships. This needs to be extended to three, five, an arbitrary amount.

What I have tried

The first thing I tried was:

MATCH (node1:Label1)-[:REL1|:REL2]->(node2)
RETURN node1, collect(node2)

Collecting node2 would combine the results of different labels in one list under one column, so that would not work.

This post explains why using multiple matches won't work. (TLDR: it turns into an AND condition, as opposed to the OR type I am looking for.

Writing two separate queries and using UNION to combine them would not work, as unions need the RETURN structures to be the same, as per the docs. In my case, the first query would look like RETURN node1, collect(nodeRel1), and the second like RETURN node1, collect(nodeRel2), which are of different types.

What now?

I figured I would be able to achieve this by using RETURN as follows:

RETURN node1, collect(nodeRel1), collect(nodeRel2)

Now, however, I am quite lost when it comes to writing the MATCH clause. What query would give me the desired data? And, equally important, why?

Thanks in advance, Nils

Nils
  • 520
  • 7
  • 15

1 Answers1

1

There are several options here, one of them is: MATCH the origin node and then OPTIONAL MATCH which relationship type you need (since it is not mandatory that it will exist). The last part is to collect each type's nodes

MATCH (n:Person)
WITH n
OPTIONAL MATCH (n)-[:LIKES]-(m)
WITH n, m
OPTIONAL MATCH (n)-[:LOVES]-(t)
RETURN n, collect(distinct(m)) as likes, collect(distinct(t)) as loves

For this sample data:

MERGE (b:Person {name: "Bob" })
MERGE (c:Person {name: "Charles" })
MERGE (a:Person {name: "Anna" })
MERGE (d:Person {name: "Kira" })
MERGE (e:Person {name: "Dan" })
MERGE (f:Person {name: "El" })

MERGE (a)-[:LIKES]-(b)
MERGE (a)-[:LIKES]-(c) 
MERGE (a)-[:LIKES]-(d) 
MERGE (e)-[:LOVES]-(a)
MERGE (e)-[:LOVES]-(b) 
MERGE (f)-[:LOVES]-(a) 
MERGE (d)-[:LOVES]-(b) 
MERGE (f)-[:LOVES]-(a) 

It gave me this:

╒══════════════════╤════════════════════════════╤════════════════════════════╕
│"n"               │"likes"                     │"loves"                     │
╞══════════════════╪════════════════════════════╪════════════════════════════╡
│{"name":"Dan"}    │[]                          │[{"name":"Bob"},{"name":"Ann│
│                  │                            │a"}]                        │
├──────────────────┼────────────────────────────┼────────────────────────────┤
│{"name":"El"}     │[]                          │[{"name":"Anna"}]           │
├──────────────────┼────────────────────────────┼────────────────────────────┤
│{"name":"Bob"}    │[{"name":"Anna"}]           │[{"name":"Dan"},{"name":"Kir│
│                  │                            │a"}]                        │
├──────────────────┼────────────────────────────┼────────────────────────────┤
│{"name":"Charles"}│[{"name":"Anna"}]           │[]                          │
├──────────────────┼────────────────────────────┼────────────────────────────┤
│{"name":"Anna"}   │[{"name":"Charles"},{"name":│[{"name":"El"},{"name":"Dan"│
│                  │"Kira"},{"name":"Bob"}]     │}]                          │
├──────────────────┼────────────────────────────┼────────────────────────────┤
│{"name":"Kira"}   │[{"name":"Anna"}]           │[{"name":"Bob"}]            │
└──────────────────┴────────────────────────────┴────────────────────────────┘
nimrod serok
  • 14,151
  • 2
  • 11
  • 33
  • `MATCH (t)-[:REL1]-(n:Person)-[:REL2]-(m)` works for two relationships. I have updated the question, thank you. – Nils May 27 '22 at 16:00
  • 1
    Updated the answer to support several types – nimrod serok May 27 '22 at 16:05
  • Why are the first and second match the same, aside from the `OPTIONAL` match and the label being specified on `n`? This also does not seem to work on my own data set (I only get the results of the first relationship), which seems to only differ in the labels not being the same on each target node. Do you have any ideas on what might be going wrong? @nimrod serok – Nils May 27 '22 at 16:22
  • Updated the first match. My bad – nimrod serok May 27 '22 at 16:24
  • Ah, so this way you make the origin node mandatory to retrieve, after which you optionally match any relationships. Smart! Thank you very much sir. Have a great day! – Nils May 27 '22 at 16:25