Create a graph with CALL apoc.do.when

Hi! I need to write a query, where will be created a graph by these rules:

  • create three types of nodes:
    if goodParent = true, create the node with ChildGood;
    if goodParent = false, create the node with ChildBad;
    for every animal create a node.

  • create relationships between these nodes:
    if animals: bigP - create the "BIG_P" relationship
    if animals: smallA- create the "SMALL_A" relationship

CALL apoc.load.json("fileName")  
YIELD value as v UNWIND v.animals.bigP as p 
 
MERGE (animalP:AnimalP {name:p}) WITH v, animalP

CALL apoc.do.when(v.goodParent=false,  
	'MERGE (childB:ChildBad{name:name}) MERGE (childB)-[:BIG_P]->(animalP)',   
	'MERGE (childG:ChildGood{name:name}) MERGE (childG)-[:BIG_P]->(animalP)',   
	{v: v}) YIELD value  
WITH v, animalP

UNWIND v.animals.smallA as a  
MERGE (animalA:AnimalA {name:a})

WITH v, animalA 

CALL apoc.do.when(v.goodParent=false,  
	'MATCH (childB:ChildBad) 
	MERGE (childB)-[:SMALL_A]->(animalA)',   
	'MATCH (childG:ChildGood) 
	MERGE (childG)-[:SMALL_A]->(animalA)',   
	{v: v}) YIELD value 
RETURN value

Why can't I use "apoc.do.when"? It doesn't work here

In your first usage of apoc.do.when you need to use v.name instead of name when merging the ChildBad/Good nodes. The inner cypher statement does not have access to the outer namespace, you need to pass in everything you need via the params map.

The 2nd usage of apoc.do.when does not use the params ap all. I assum you need to do MATCH (child:ChildBad[name:v.name}) instead.

Thank you Stefan!
Is exist a way to call apoc.do.when second time?
I'm not fully understand about
MATCH (child:ChildBad[name:v.name})
Where put it?

Hi Pavlo,

if you return in the first case.do.when the child in both cases under the very same name child you don't need the second case.do.when:

YIELD value as v UNWIND v.animals.bigP as p 
 
MERGE (animalP:AnimalP {name:p}) WITH v, animalP

CALL apoc.do.when(v.goodParent=false,  
	'MERGE (childB:ChildBad{name:v.child.name}) MERGE (childB)-[:BIG_P]->(animalP) return childB as child',   
	'MERGE (childG:ChildGood{name:v.child.name}) MERGE (childG)-[:BIG_P]->(animalP) return childG as child',   
	{v: v}) YIELD value  
WITH v, animalP, value.child as child

UNWIND v.animals.smallA as a  
MERGE (animalA:AnimalA {name:a})

WITH v, animalA 
MERGE (child)-[:SMALL_A]->(animalA)
RETURN child, animalA

Note: I didn't actually run and test that statement, but the idea should be clear.

1 Like

Thank you!
But It doesn't work.
If I do it:

WITH v, animalP, value.child as child

UNWIND v.animals.smallA as a  
MERGE (animalA:AnimalA {name:a})

WITH v, animalA 
MERGE (child)-[:SMALL_A]->(animalA)
RETURN child, animalA

There aren't created the relationship :SMALL_A and nodes AnimalA
Could I fix it?

You are not passing child through in your last WITH

1 Like

Stefan and Michael thank you very much!