1

This is my Query:

MATCH (a:Person {name: "Stefan"})

MATCH (p:Person {name: "not_a_real_name"})
CALL apoc.path.subgraphNodes(p, {
    relationshipFilter: "KNOWS"
})
YIELD node AS b

RETURN a

a and b will always return (no records) since "not_a_real_name" is not a real name.

I'm trying to keep the a-node, no matter if the called procedure returns records or not. I think i'm looking for some kind of OPTIONAL MATCH. Changing "not_a_real_name" for "Praveena" will return the right result.

I'm working on this data:

MERGE (mark:Person:DevRel {name: "Mark"})
MERGE (lju:Person:DevRel {name: "Lju"})
MERGE (praveena:Person:Engineering {name: "Praveena"})
MERGE (zhen:Person:Engineering {name: "Zhen"})
MERGE (martin:Person:Engineering {name: "Martin"})
MERGE (joe:Person:Field {name: "Joe"})
MERGE (stefan:Person:Field {name: "Stefan"})
MERGE (alicia:Person:Product {name: "Alicia"})
MERGE (jake:Person:Product {name: "Jake"})
MERGE (john:Person:Product {name: "John"})
MERGE (jonny:Person:Sales {name: "Jonny"})
MERGE (anthony:Person:Sales {name: "Anthony"})
MERGE (rik:Person:Sales {name: "Rik"})

MERGE (zhen)-[:KNOWS]-(stefan)
MERGE (zhen)-[:KNOWS]-(lju)
MERGE (zhen)-[:KNOWS]-(praveena)
MERGE (zhen)-[:KNOWS]-(martin)
MERGE (mark)-[:KNOWS]-(jake)
MERGE (alicia)-[:KNOWS]-(jake)
MERGE (jonny)-[:KNOWS]-(anthony)
MERGE (john)-[:KNOWS]-(rik)

MERGE (alicia)-[:FOLLOWS]->(joe)
MERGE (joe)-[:FOLLOWS]->(mark)
MERGE (joe)-[:FOLLOWS]->(praveena)
MERGE (joe)-[:FOLLOWS]->(zhen)
MERGE (mark)-[:FOLLOWS]->(stefan)
MERGE (stefan)-[:FOLLOWS]->(joe)
MERGE (praveena)-[:FOLLOWS]->(joe)
MERGE (lju)-[:FOLLOWS]->(jake)
MERGE (alicia)-[:FOLLOWS]->(jonny)
MERGE (zhen)-[:FOLLOWS]->(john)
MERGE (anthony)-[:FOLLOWS]->(joe)

2 Answers2

1

Found another way that may require less nesting of apoc.when for very complicated queries:

MATCH (a:Person {name: "Stefan"})
Call {
    MATCH (p:Person {name: "xxxx"})
    CALL apoc.path.subgraphNodes(p, {relationshipFilter: "KNOWS"})
    YIELD node
    return collect(node) as subGraphNodesList
}
UNWIND (CASE subGraphNodesList WHEN [] then [null] else subGraphNodesList end) 
as subGraphNodes
RETURN subGraphNodes, a
0

You can use apoc.when (or apoc.do.when) for this purpose. Line 2 uses OPTIONAL match so that it will return a row even if it does not return any result. Line 3 is checking if previous line 2 returns a row (p). If yes, then execute the call to apoc.path.subgraphNodes. Then last parameter is the trick. You should pass a parameter p to person because it is not visible to the inner CALL. The outer CALL apoc.when needs to pass p as person for the 2nd CALL apoc.path. If p is null, then just return a null value and the query will still return a.

MATCH (a:Person {name: "Stefan"})
OPTIONAL MATCH (p:Person {name: "not_a_real_name"})
CALL apoc.when(p is not null,
  'CALL apoc.path.subgraphNodes(person, {
    relationshipFilter: "KNOWS"}) YIELD node AS b RETURN b',
  'RETURN NULL',
  {person:p}
)
YIELD value as nodes
RETURN  a, nodes

enter image description here

jose_bacoy
  • 12,227
  • 1
  • 20
  • 38