Returning a node from a call to apoc.do.when

Hi,

I am trying to use the apoc.do.when to conditionally create a node if a given column on the input CSV file has data. If the node is created, I want to return it and use it further to create additional edges.

WITH map.countryCode AS countryCode, addr AS addr
CALL apoc.do.when((countryCode IS NOT NULL),
  'MERGE (ctry:Country {code: countryCode}) RETURN ctry',
  '',
  {countryCode: countryCode, addr: addr})
YIELD value
RETURN value.node AS node

According to the document, that node is available in the value maps. However, when I try to use it further (not included in the snippet) the relationships do not get created and when I run it on the browser it shows the node as null. Following another post recommendation, if I return '1' instead of 'ctry', and run through the browser, it prints 1.
Can someone explain to me what is happening or what am I doing wrong in this case ?

use value.ctry instead of value.node. That is how you access any value you return.

Hi Gary,

When I modify the code to do that:

WITH map.countryCode AS countryCode, addr AS addr
CALL apoc.do.when((countryCode IS NOT NULL),
  'MERGE (ctry:Country {code: countryCode}) RETURN ctry',
  '',
  {countryCode: countryCode, addr: addr})
YIELD value
RETURN value.ctry AS ctry
}

I end up with this execution failed error:

Odd. How are you executing it? In browser or driver?

I have been executing it in the browser. Note that this is part of a larger script that loads a CSV record into a map and starts processing it using the LOAD CSV procedure.

The whole thing is encapuslated in a

CALL apoc.load.csv('file:///customers.csv', {,
...
}
}
RETURN ctry
}
IN TRANSACTIONS OF 500 ROWS
RETURN ctry

When I run the same call outside, it seems to work as expected.

I looked at the logs and found a "Caused by: org.neo4j.graphdb.NotInTransactionException: The transaction has been closed." exception being thrown.

I got the same exception. Looks like the node returned can only be consumed within the call subquery because of the 'In transactions', as the transaction it was bound to has closed because of the batching.

As a work around, return the information you need from the node, such as properties(value.ctry), labels(value.ctry), id(value.ctry), elementId(value.ctry), etc.

You can always match for the node by elementId/id if you need to do some additional processing after the batch or really want the node returned.

CALL apoc.load.csv('file:///customers.csv', {,
...
}
}
RETURN id(value.ctry) as id
}
IN TRANSACTIONS OF 500 ROWS
MATCH(n) where id(n) = id
RETURN n
1 Like

It makes sense now and thanks for the explanation. I will give it a go with the rematching the node based on the property.

I'd get completely away from using apoc.do.when and use a CALL instead. In my example below if countryCode is NULL then a null will be returned by the CALL otherwise the CALL will return the node.

Example:

WITH map.countryCode as countryCode, addr as addr
CALL {
    WITH countryCode, addr
    WITH countryCode, addr WHERE countryCode IS NOT NULL

    MERGE (ctry:Country {code: countryCode })

    RETURN ctry
}
RETURN ctry as node

As a side note: We have found that the CALL consumes considerably less resources than the apoc.do.when allowing more records to be processed in a given time frame.

1 Like

This will only work on later versions of Neo4j. I think it is 4.2 or better.

Thanks @myron_higerd. I tried your solution; it worked perfectly and is much easier to read than my original approach.