Rémi Chaffard
Rémi Chaffard

Reputation: 87

Neo4j detect node modification

I'm using such kind of query in Neo4j database:

MERGE(n:type {key:"xyz"})
ON CREATE SET n.create_date = timestamp() 
ON MATCH SET n.update_date = timestamp()
SET n.att1=value1, n.att2=value2

The ON MATCH will help me to identify if a node has been found, but not if attributes have really been changed.

Is there any way we can use so we can detect that any attribute of a node has been changed ? For instance running the same query once again will change update_date attribute without really changing attributes. I would like to be able to detect that att1 or att2 has been changed.

Thanks a lot

Upvotes: 0

Views: 797

Answers (2)

Rémi Chaffard
Rémi Chaffard

Reputation: 87

Based on the excellent support from Christophe, I played a bit with apoc and used this solution to create a trigger for all properties starting with u_

CALL apoc.meta.data() YIELD label, property, elementType WHERE elementType = "node" AND property =~ "^u_.*" WITH DISTINCT property AS key
CALL apoc.trigger.add(
'trig_upd_'+key,
'UNWIND apoc.trigger.propertiesByKey({assignedNodeProperties},"'+key+'") as prop
WITH prop.old as oldProp, prop.new as newProp, prop.node AS n
SET n.last_updated = timestamp()', {phase:'before'})
YIELD name
RETURN name;

I will continue to play with this, goal now is to find a way to create or remove the triggers in case of new or deleted properties.

BR Rémi

Upvotes: 1

Christophe Willemsen
Christophe Willemsen

Reputation: 20185

It is possible with APOC Triggers :

First, download and install APOC and enable it :

apoc.trigger.enabled=true
dbms.security.procedures.unrestricted=apoc.trigger.*
dbms.security.procedures.whitelist=apoc.*

You can then add a trigger that will react when an attr1 property is changed :

CALL apoc.trigger.add(
'updateTimestamp',
'UNWIND apoc.trigger.propertiesByKey({assignedNodeProperties},"attr1") as prop
WITH prop.old as oldProp, prop.new as newProp, prop.node AS n 
SET n.updated_at = timestamp()', {phase:'before'});

Test it :

CREATE (n:Node) SET n.attr1 = "hello"
MATCH (n:Node) RETURN n
╒════════════════════════════════════════════╕
│"n"                                         │
╞════════════════════════════════════════════╡
│{"updated_at":1543313569105,"attr1":"hello"}│
└────────────────────────────────────────────┘

Update the node :

MATCH (n:Node) SET n.attr1 = "hellonew"
MATCH (n:Node) RETURN n
╒═══════════════════════════════════════════════╕
│"n"                                            │
╞═══════════════════════════════════════════════╡
│{"updated_at":1543313626248,"attr1":"hellonew"}│
└───────────────────────────────────────────────┘

Do it again to check it is not triggered when the property is not changed :

MATCH (n:Node) SET n.attr1 = "hellonew"
MATCH (n:Node) RETURN n
╒═══════════════════════════════════════════════╕
│"n"                                            │
╞═══════════════════════════════════════════════╡
│{"updated_at":1543313626248,"attr1":"hellonew"}│
└───────────────────────────────────────────────┘

Upvotes: 4

Related Questions