cancel
Showing results for 
Search instead for 
Did you mean: 

How to define a VOID custom procedure with side effects?

benjamin_rood
Node Clone

I am having a bit of difficulty knowing how to define a procedure using apoc.custom.declareProcedure / apoc.custom.asProcedure that modifies a node and returns nothing (void):

 

CALL apoc.custom.declareProcedure(
  'updateNodeMetadata(node::NODE) :: VOID',
  'WITH datetime.realtime() AS now, $node AS node, $node.objectVersion AS oldVersion
  SET node.lastChangedAt = now
  SET node.objectVersion = CASE WHEN oldVersion IS NULL THEN 1 ELSE oldVersion + 1 END',
  'write');

 

I want to take a node as an argument, and modify a couple of metadata fields on the node.

When I look at the logs for why this fails, the logs say the following, but the function *is* defined as VOID already?

 

022-08-10 11:30:25.579+0000 ERROR [a.c.CypherProcedures] [neo4j] Could not register procedure: custom.updateNodeMetadata with WITH datetime.realtime() AS now, $node AS node, $node.objectVersion AS oldVersion
  SET node.lastChangedAt = now
  SET node.objectVersion = CASE WHEN oldVersion IS NULL THEN 1 ELSE oldVersion + 1 END RETURN
 accepting[node = null :: NODE?] resulting in [] mode WRITE Procedures with zero output fields must be declared as VOID
org.neo4j.internal.kernel.api.exceptions.ProcedureException: Procedures with zero output fields must be declared as VOID

 

 

1 ACCEPTED SOLUTION

glilienfield
Ninja
Ninja

 I took your code as is and pasted it into my desktop and it worked.  I am using APOC 4.4.0.8.  

View solution in original post

3 REPLIES 3

benjamin_rood
Node Clone

It works if I use apoc.custom.asProcedure like this:

 

 

 

CALL apoc.custom.asProcedure(
  'updateNodeMetadata',
  'WITH datetime.realtime() AS now, $node AS node, $node.objectVersion AS oldVersion
  SET node.lastChangedAt = now
  SET node.objectVersion = CASE WHEN oldVersion IS NULL THEN 1 ELSE oldVersion + 1 END',
  'write', [['value', 'VOID']],
  [['node', 'NODE']], "")

 

 

But I should say that the problem with this of course, is that you still need to YIELD the result, even though it's NULL, which is annoying.

If I define it as a function, this is the best I can get:

CALL apoc.custom.declareFunction(
  'unm(node::NODE) :: MAP',
  'WITH datetime.realtime() AS now, $node AS node, $node.objectVersion AS oldVersion
  SET node.lastChangedAt = now
  SET node.objectVersion = CASE WHEN oldVersion IS NULL THEN 1 ELSE oldVersion + 1 END
  RETURN NULL')

 

 

But  this is not callable unless the database user is an admin:

ERROR: Neo.ClientError.Security.Forbidden
Write operations are not allowed for user 'neo4j' with roles [admin] restricted to READ.

glilienfield
Ninja
Ninja

 I took your code as is and pasted it into my desktop and it worked.  I am using APOC 4.4.0.8.  

Ah, okay, our cluster is still stuck on 4.0.x

Supplemental question: Any way of CALL-ing a VOID procedure and skipping the YIELD step?

Nodes 2022
Nodes
NODES 2022, Neo4j Online Education Summit

On November 16 and 17 for 24 hours across all timezones, you’ll learn about best practices for beginners and experts alike.