Neo4j trigger Expected parameter(s)

I have a trigger such that:

CALL apoc.trigger.add('segment_3', '
WITH $createdNode AS accountAction
MATCH (player:Player)
WHERE player.playerId = accountAction.playerId
WITH player
MATCH (aca:AccountAction)<-[:PLAYER_ACCOUNT_ACTION]-(aaha:AccountActionHourlyAggregate)<-[paat:PLAYER_ACCOUNT_ACTION_TIME]-(aada:AccountActionDailyAggregate)<-[paad:PLAYER_ACCOUNT_ACTION_DATE]-(player)
WHERE date(paad.date) >= date("2024-02-01") AND date(paad.date) <= date("2024-02-20")
WITH player, COLLECT({action: aca, amount: aca.amount}) AS actions
WITH player, REDUCE(total = 0, action IN actions | total + action.amount) AS totalAmount
WHERE totalAmount > 100
MATCH (trigger:SegmentationNodeMetadata {name: "segment_3"})
MERGE (trigger)-[:RTPG_OWNS]->(player)
WITH player
CALL apoc.log.info("Trigger segment_3 fired for player with ID: " + player.playerId)
', {phase: 'afterAsync'})

the desired action is any time a accountAction is created the sum of all the player in
question accountAction.amount are added up and if over 100 then a realship is created
bettween the player and a group. I belive the logic in the trigger is mostly correct
but is missing something as the log shows :

Error executing trigger segment_4 in phase afterAsync
org.neo4j.graphdb.QueryExecutionException: Expected parameter(s): createdNode

i'm using neo4j 5.1.0

I believe the error is caused because the value is 'createdNodes' (plural), not 'createdNode' (singular) as you have in your query.

Comments:

The value of $createdNodes is a list, so you should 'unwind' it and process each created node. Also, this is called for all nodes created, do you want to filter upfront to only execute the trigger for those created AccountAction nodes?

You should be able to simplify the following:

WITH player, COLLECT({action: aca, amount: aca.amount}) AS actions
WITH player, REDUCE(total = 0, action IN actions | total + action.amount) AS totalAmount

with:

WITH player, sum(aca.amount) AS totalAmount

Hi Gary
"'createdNodes' (plural), not 'createdNode' (singular)" ouch!!!!
Thanks for taking the time to correct that.
your right it should only execute the trigger for those created AccountActions
how would I go about that. neo4j and cypher is still quite new to me
( an old proj I've been asked to pick up)

Try this.

CALL apoc.trigger.add('segment_3', 
'
UNWIND $createdNodes AS createdNode
WITH createdNode
WHERE createdNode:AccountAction
MATCH (player:Player)
WHERE player.playerId = createdNode.playerId
MATCH (aca:AccountAction)<-[:PLAYER_ACCOUNT_ACTION]-(:AccountActionHourlyAggregate)<-[:PLAYER_ACCOUNT_ACTION_TIME]-(:AccountActionDailyAggregate)<-[paad:PLAYER_ACCOUNT_ACTION_DATE]-(player)
WHERE date("2024-02-01") <= date(paad.date) <= date("2024-02-20")
WITH player, SUM(aca.amount) AS totalAmount
WHERE totalAmount > 100
MATCH (trigger:SegmentationNodeMetadata {name: "segment_3"})
MERGE (trigger)-[:RTPG_OWNS]->(player)
WITH player
CALL apoc.log.info("Trigger segment_3 fired for player with ID: " + player.playerId)
', 
{phase: 'afterAsync'})

One comment I have is with your use of a fixed date range. How is this trigger going going to work as time moves forward and the range represents the past? Do you want a sliding window X days?

Finally, the documentation for apoc 5.15 (which I have installed) states the apoc.trigger.add procedure has been deprecated. The new procedure is apoc.trigger.install.

1 Like

Hi Gary
I'll upgrade to the lastest will your fix still work? with regards to the date range it's usally static and I'm using strings to miniulaplation in the trigger?
what i will ask is when you state the original trigger will go though all nodes does that mean every AccountAction node in the db
or every AccountAction node that belongs to the player it sounds a silly question buy as said I'm not familiar to the neo4j db
if it's the later then it's what's intended

Yes it will still work. The new procedure only differs by the addition of a “database” name parameter.

The trigger will get called for every change. The trigger is passed the changes in the lists. You are utilizing the createdNodes lists, because you want to detect new nodes when created. The trigger will get called for any type of node created, that is why I added the “with” clause that passes createdNodes with the label AccountAction.

1 Like