Reputation: 84
I have these nested nodes that I wanted to extract out. A one to many to many relationships of nodes. I used the following cypher to do it.
WITH (o:order)
WHERE ID(o) = <some id>
OPTIONAL MATCH (o) -[:ORDER_INCLUDES]-> (p:pizza)
WITH o, p
OPTIONAL MATCH (p) -[:WITH_TOPPING]-> (t:topping)
WITH o, {
pizza: p,
toppings: COLLECT(DISTINCT t)
} AS pi
RETURN o, COLLECT(DISTINCT pi) AS pizzas
When theres none of the pizza with toppings, I get the result I wanted which is 1 record or order with the pizzas. Note that the toppings are always optional.
1. Order [
Tomato Pizza,
Tomato Pizza
]
However when theres toppings involved, it returns the pizza in separate records
1. Order [ [
Tomato Pizza Pineapple Topping,
] Chicken Topping
]
2. Order [
Tomato Pizza
]
Which isn't what I want since the 2 pizzas belong to the same orders. I must be doing something wrong, please help.
Edited:--
Sorry, I missed out a huge detail that causes this problem. I collected the time for when the pizza is created at the beginning.
WITH (o:order)
WHERE ID(o) = <some id>
OPTIONAL MATCH (o) -[:ORDER_INCLUDES]-> (p:pizza)
OPTIONAL MATCH (e:event) WHERE (e) -[:FOR]-> (o) OR (e) -[:FOR]-> (pizza)
WITH o, MAX(e.time) AS time, p
OPTIONAL MATCH (p) -[:WITH_TOPPING]-> (t:topping)
OPTIONAL MATCH (p) <-[:FOR]- (e:event)
WITH o, {
pizza: p,
time: MAX(e.time),
toppings: COLLECT(DISTINCT t)
} AS pi
RETURN o, time, COLLECT(DISTINCT pi) AS pizzas
That time was the culprit, this problem is resolved when I remove the time.
Upvotes: 1
Views: 35
Reputation: 84
To prevent the record from splitting, the following had to be removed
OPTIONAL MATCH (e:event) WHERE (e) -[:FOR]-> (o) OR (e) -[:FOR]-> (pizza)
Now this is the solution I'm working with
WITH (o:order)
WHERE ID(o) = <some id>
OPTIONAL MATCH (o) -[:ORDER_INCLUDES]-> (p:pizza)
WITH o, p
OPTIONAL MATCH (p) -[:WITH_TOPPING]-> (t:topping)
OPTIONAL MATCH (p) <-[:FOR]- (e:event)
WITH o, {
pizza: p,
time: MAX(e.time),
toppings: COLLECT(DISTINCT t)
} AS pi
RETURN o, MAX(pi.time) AS time, COLLECT(DISTINCT pi) AS pizzas
Upvotes: 0
Reputation: 5385
This should work (first collect the toppings for each pizza, then collect the pizzas and their toppings)
MATCH (o:order)
WHERE id(o) = $id
OPTIONAL MATCH (o)-[:ORDER_INCLUDES]-> (p:pizza)
WITH o, p
OPTIONAL MATCH (p) -[:WITH_TOPPING]-> (t:topping)
WITH o,p, COLLECT(t) AS toppings
RETURN o,COLLECT ({pizza:p,toppings:toppings}) AS pizzas
Buon appetito
Upvotes: 1