cancel
Showing results for 
Search instead for 
Did you mean: 

Duplicated rows when using multiple CALL subqueries

Hi Everyone!

I need some help with building a Cypher query for my problem.

Given the following schema:

I want to fetch all the children(blue/yellow node), parents(yellow node), and the respective properties(gray node) of their location(green node). Basically, have the following output at the end:

Parent (yellow node) Child (yellow/blue) Parent_property(gray) Child_property(gray)

For that, I used UNION to get parent_ids/child_ids from the yellow and blue nodes under same column names, and built 2 separate CALL subqueries (one to fetch id information, and the other for property information). However, I don't know how to proceed next, since I obtained duplicated information after executing the cypher query as it now. I understand that this is due to how CALL subqueries work, however, I don't know how to fix that.

//Fetch all parent and children ids
CALL { 
    MATCH (c:subPart)<-[:Has_child]-(p:mainPart{id: "12345"}) RETURN c.id AS child, p.id AS parent
    UNION
    MATCH (m:mainPart)<-[:Has_child]-(p:mainPart {id: "12345"}) RETURN m.id AS child, p.id AS parent
   
} 
MATCH (p)-[]->(r)-[:Has_property]->(property1) 
CALL {
    MATCH (c)-[]->(k)-[:Has_property]->(property2) RETURN property2.name AS child_property
    UNION
    MATCH (m)-[]->(n)-[:Has_property]->(property3) RETURN property3.name AS child_property
}
RETURN child, parent, property1.name AS parent_property, child_property

I have also tried to COLLECT parent/ child ids and properties in lists and then UNWIND them, or use the WHERE EXISTS{} clause to filter for the properties, but none of this worked.

I am using Neo4j Desktop 4.3.3 version.

Any help/tips will be very much appreciated! Thank you!

2 REPLIES 2

martin3
Node Clone

Why not something like this?

MATCH (blue:BLUE)<-[HAS_CHILD]-(yellow:YELLOW {ID: X})—>(green:GREEN)-[HAS_PROPERTY]->(gray:GRAY) RETURN yellow, blue, green, gray

I guess there is a reason, and I am just wondering 🙂

glilienfield
Ninja
Ninja

This should give you a row for each child, with their parent, parent's property, and child's property as the columns.

You can replace the 'return' statement with the following return statement if you want one row per parent, with the child data collected in a list, with each element containing both the child and its property in index 0 and 1, respectively:

return parent, parentProperty, collect([child, childProperty]) as children

You can remove the 'where child:subPart or child:mainPart' clause if the child nodes don't have other labels other than these two.

match (parent:mainPart {id: "12345"})-[:Has_child]->(child where child:subPart or child:mainPart)
match (parent)--()-[:Has_property]->(parentProperty)
with parent, parentProperty, child
match (child)--()-[:Has_property]->(childProperty)
return parent, parentProperty, child, childProperty