Search code examples
neo4jcyphergraph-databasesmap-projectionscollect

How to use collect to compose a node allowing empty lists as results?


Consider a graph that looks like this:

(node) -> (related nodes)
a1 -> [b1, b2, b3]
a2 -> [b1]
a3 -> []

I want to return all the nodes extended with a list of its neighbors. My current query is the following

MATCH (x0:A)
MATCH (x1:B )
WHERE ((x0)-[:B]->(x1))
WITH x0,collect(x1) as x2
WITH x0,x0{.*, neighbors:x2} as x3
RETURN x3 as result

After executing the query I get the following result:

╒══════════════════════════════╕
│"result"                      │
╞══════════════════════════════╡
│{"name":"a1","neighbors":[{"na│
│me":"b1"},{"name":"b2"},{"name│
│":"b3"}]}                     │
├──────────────────────────────┤
│{"name":"a2","neighbors":[{"na│
│me":"b1"}]}                   │
└──────────────────────────────┘

but I want that the node "a3" to also appear in the result, like this:

╒══════════════════════════════╕
│"result"                      │
╞══════════════════════════════╡
│{"name":"a1","neighbors":[{"na│
│me":"b1"},{"name":"b2"},{"name│
│":"b3"}]}                     │
├──────────────────────────────┤
│{"name":"a2","neighbors":[{"na│
│me":"b1"}]}                   │
├──────────────────────────────┤
│{"name":"a3","neighbors":[]}  │
└──────────────────────────────┘

How should I write the query instead?


Solution

  • MATCH (x0:A)
    MATCH (x1:B )
    WHERE ((x0)-[:B]->(x1))
    

    is equivalent to

    MATCH (x0:A)-[:B]->(x1:B )
    

    Which says "match all A and their neighbors B where A has neighbors B". AKA, B is required. To make B optional, you need to use an optional match

    MATCH (x0:A)
    OPTIONAL MATCH (x0)-[:B]->(x1:B )
    

    and now the B column is allowed to be null!

    Full Query (as simplified by Cybersam)

    MATCH (x0:A)
    OPTIONAL MATCH (x0)-[:B]->(x1:B)
    RETURN x0{.*, neighbors:COLLECT(x1)} AS result;