Apoc.periodic.commit seemingly fails to parse limit parameter: NodeEntity cannot be cast to class java.lang.Long?

The apoc.periodic.commit procedure fails on me, possibly failing to parse my Cypher command. It seems that is it interpreting the value of the limit parameter as something other than an integer (or a long, to be precise). I've tried using two different drivers, and they give me slightly different errors, which I shall show.

I'm running Neo4j 4.1.1 through the official Docker image.

Below is my Cypher command.

CALL apoc.periodic.commit("MATCH (p:Person) WITH p LIMIT $limit RETURN *", {limit:1000})

I've tried running this command with the neo4j-driver v4.1.1 Python driver.

>>> result = session.run('CALL apoc.periodic.commit("MATCH (p:Person) WITH p LIMIT $limit RETURN *", {limit:1000})')
>>> result.values()
[[0, 0, 0, 1, 1, {"class org.neo4j.kernel.impl.core.NodeEntity cannot be cast to class java.lang.Long (org.neo4j.kernel.impl.core.NodeEntity is in unnamed module of loader 'app'; java.lang.Long is in module java.base of loader 'bootstrap')": 1}, 0, {}, False]]

Below I used the py2neo v5.0b1 Python driver, giving a similar error.

>>> result = graph.run('CALL apoc.periodic.commit("MATCH (p:Person) WITH p LIMIT $limit RETURN *", {limit:1000})')
>>> result
 updates | executions | runtime | batches | failedBatches | batchErrors                                                                                                                                              | failedCommits | commitErrors | wasTerminated 
---------|------------|---------|---------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|--------------|---------------
       0 |          0 |       0 |       1 |             1 | {`class java.lang.String cannot be cast to class java.lang.Long (java.lang.String and java.lang.Long are in module java.base of loader 'bootstrap')`: 1} |             0 | {}           | false 

EXPLAIN output

The execution plan of the command shown here: https://gist.github.com/olavurmortensen/2af61e9164fe57711318595bff404756

PROFILE output

The profile of the command is shown here: https://gist.github.com/olavurmortensen/1c71da98a7fe1ad17776f4a4998cb8e3

Apoc periodic procedures are used to periodically update the graph in batches and cannot be used to return results in batches.

Specifically, the apoc.periodic.commit expects the return to be an integer, so that is why you are seeing your error. If you look at the documentation it returns the count(*) to know when to stop the batching process.

call apoc.periodic.commit("
match (user:User) WHERE exists( user.city )
with user limit {limit}
MERGE (city:City {name:user.city})
MERGE (user)-[:LIVES_IN]->(city)
REMOVE user.city
RETURN count(*)
",{limit:10000})
1 Like

That seems to have solved it. Thank you.

The documentation says the following about apoc.periodic.commit. I think it could say explicitly that the query has to end with RETURN count(*).

The query is executed repeatedly in separate transactions until it returns 0.

It's still not working though, but probably for a different reason.

The following simple query does it's job correctly and quickly.

MATCH (p:Person) WITH p LIMIT 1000 RETURN count(*)

Trying to run the same query using apoc.periodic.commit, it just hangs.

CALL apoc.periodic.commit("
MATCH (p:Person)
WITH p LIMIT $limit
RETURN count(*)", {limit:1000})