Creating triggers

Hello,

I am attempting to use an apoc.trigger in order to create a set of nodes after a node - with a specific label - is created. However, it doesn't seem to be working.

I updated/added the apoc.conf with the appropriate statements to enable apoc.trigger. I'm able to use apoc.trigger functions including installing a trigger.

BUT, it's still not working for some reason. When I create new nodes, the trigger is not activated.

Any thoughts on what I may be missing?

@jacob3

Neo4j version?
APOC version?

Can you share the cypher used to create the trigger?

Neo4j Version: 5.11 enterprise
APOC Version: 5.11 core

@jacob3

or is that not possible?

Here is the cypher that creates the trigger (in the system database. I changed the node labels to remove info that I couldn't share. :slight_smile:

CALL apoc.trigger.install(
    'dev',
    'create-class-new-user',
    "UNWIND $createdNodes AS n
    WHERE n:User AND NOT (n)-[:PREFERS]->(:School)
    CREATE (p:School)
    SET
        p.id = randomUUID(),
        p.isPrimary = true,
        p.createdAt = datetime(),
        p.modifiedAt = datetime()
    WITH p
    CREATE (d1:Department {name: 'Math'})
    SET d1.id = randomUUID(), d1.createdAt = datetime(), d1.modifiedAt = datetime(), d1.isPrimary = false
    CREATE (p)-[:HAS_DEPARTMENT]->(d1)
    CREATE (d2:Department {name: 'Science'})
    SET d2.id = randomUUID(), d2.createdAt = datetime(), d2.modifiedAt = datetime(), d2.isPrimary = false
    CREATE (p)-[:HAS_DEPARTMENT]->(d2)
    WITH d1, d2
    CREATE (t:Category {name:'Monday'})
    SET 
        t.id = randomUUID(),
        t.createdAt = datetime(),
        t.modifiedAt = datetime()
    CREATE (d1)-[:PREFERS]->(t)
    CREATE (d2)-[:PREFERS]->(t)
    WITH d1, d2
    CREATE (t:Category {name:'Tuesday'})
    SET 
        t.id = randomUUID(),
        t.createdAt = datetime(),
        t.modifiedAt = datetime()
    CREATE (d1)-[:PREFERS]->(t)
    CREATE (d2)-[:PREFERS]->(t)
    WITH d1, d2
    CREATE (t:Category {name:'Wednesday'})
    SET 
        t.id = randomUUID(),
        t.createdAt = datetime(),
        t.modifiedAt = datetime()
    CREATE (d1)-[:PREFERS]->(t)
    CREATE (d2)-[:PREFERS]->(t)
    WITH d1, d2
    CREATE (t:Category {name:'Thursday'})
    SET 
        t.id = randomUUID(),
        t.createdAt = datetime(),
        t.modifiedAt = datetime()
    CREATE (d2)-[:PREFERS]->(t)
    WITH d1, d2
    CREATE (t:Category {name:'Friday'})
    SET 
        t.id = randomUUID(),
        t.createdAt = datetime(),
        t.modifiedAt = datetime()
    CREATE (d1)-[:PREFERS]->(t)", {phase:'afterAsync'})

@jacob3

have u tried with a simpler trigger definition as a means to debug.
Given

UNWIND $createdNodes AS n
    WHERE n:User AND NOT (n)-[:PREFERS]->(:School)
    CREATE (p:School)

are any :School nodes created?
If you remove the WHERE clause are any :School nodes created?

Removing the where clause doesn't seem to work either.

Am I not allowed to create a new node in a trigger?

@jacob3
given the current issue and rather than building out a trigger with a lot of complexity, I decided to build out a very small test case. And with Neo4j 5.11.0 and

ls -al plugins/
drwxr-xr-x  2 neo4j neo4j     4096 Jan 11 22:24 .
drwxr-xr-x 15 neo4j neo4j     4096 Dec  5 11:22 ..
-rw-r--r--  1 neo4j neo4j 14495768 Jan 11 22:24 apoc-5.11.0-core.jar
-rw-rw-r--  1 neo4j neo4j 11137885 Dec  5 11:20 apoc-5.11.0-extended.jar
-rw-r--r--  1 neo4j neo4j     2217 Aug  8 07:47 README.txt

and apoc.conf defined as

cat ../conf/apoc.conf
apoc.trigger.enabled=true
apoc.trigger.refresh=60000

and then i defined trigger as follows

@system> CALL apoc.trigger.install(
             'neo4j',
             'create-class-new-user',
             "UNWIND $createdNodes AS cN create(n:Result {nodes:id(cN)})",{});

which does nothing more than for the nodes creates define a new node :Result and set its nodes: property to be the id of the node created.

And thus

@neo4j> match (n:Test) return n;
+---+
| n |
+---+
+---+

0 rows
ready to start consuming query after 96 ms, results consumed after another 3 ms
@neo4j> match (n:Result) return n;
+---+
| n |
+---+
+---+

0 rows
ready to start consuming query after 3 ms, results consumed after another 3 ms
@neo4j> unwind range(1,5) as x create (n:Test {id:x});
0 rows
ready to start consuming query after 8 ms, results consumed after another 0 ms
Added 5 nodes, Set 5 properties, Added 5 labels
@neo4j> match (n:Test) return n.id, id(n);
+--------------+
| n.id | id(n) |
+--------------+
| 1    | 10101 |
| 2    | 10102 |
| 3    | 10103 |
| 4    | 10104 |
| 5    | 10105 |
+--------------+

5 rows
ready to start consuming query after 4 ms, results consumed after another 4 ms

@neo4j> match (n:Result) return n order by n.nodes asc;;
+--------------------------+
| n                        |
+--------------------------+
| (:Result {nodes: 10101}) |
| (:Result {nodes: 10102}) |
| (:Result {nodes: 10103}) |
| (:Result {nodes: 10104}) |
| (:Result {nodes: 10105}) |
+--------------------------+

5 rows
ready to start consuming query after 73 ms, results consumed after another 7 ms

so would seem to work for me.

1 Like

Thanks @dana_canzano for looking into this.

What worked for me was keeping the phase parameter undefined, i.e. "CALL apoc.trigger.install("", "", {})".

Now it's working!

There is another option besides APOC, we have introduced Change Data Capture (CDC) in Neo4j, it is currently available as a beta in versions from Neo4j 5.14 Enterprise. You can create selectors which watch for specific labels, when a node is created a change event will be created and you can then use that to perform the desired action Introduction - Change Data Capture

2 Likes