Triggers
Database triggers are an integral part of most database systems. A trigger is a procedural code that is automatically executed in response to specific events. Events are related to some change in data, such as created, updated and deleted data records. The trigger is often used for maintaining the integrity of the information in the database.
Memgraph supports running openCypher clauses after a certain event happens
during database transaction execution, i.e. triggers. For example, when a new
Employee
node is added, all relevant relationships should be created. Triggers
can also be used to log historical data, for example, to keep track of
employees' previous salaries.
You can create, delete and print triggers. All the triggers are persisted on the disk, so no information is lost on database reruns.
Create a trigger
To create a new trigger, use a query of the following format:
CREATE TRIGGER trigger_name [ ON [ () | --> ] CREATE | UPDATE | DELETE ]
[ BEFORE | AFTER ] COMMIT
EXECUTE openCypherStatements
The first line creates a trigger with a certain name and defines event type.
Event type determines what event will trigger the execution of Cypher
statements. The event type can be the creation, updated or deletion of nodes ( ()
)
or relationships ( -->
) before or after the commitment of that transaction.
Let's break down each element of the query.
Trigger name
Each created trigger must have a globally unique name. Two triggers can't have the same name even if they apply to different events.
Event type
The event type defines what will trigger the execution of certain Cypher statements.
There are three main event types:
- CREATE
- UPDATE
- DELETE
Each event type can be fined tuned to trigger the execution only when nodes were
modified by adding ()
, when relationships were modified by adding -->
or when
any object was modified by not defining ()
or -->
in the trigger creation.
For example:
ON CREATE
- Execute certain Cypher statements if an object (node or a relationship) was created by a transaction.ON () UPDATE
- Execute certain Cypher statements if a node was updated by a transaction, perhaps a new property was added, or an existing property changed.ON --> DELETE
- Execute certain Cypher statements if a relationship was deleted by a transaction.
Event type produces information about created, updated or deleted objects within predefined variables, which can be used to write the Cypher queries trigger was set to execute.
If no event type is specified, the trigger executes its statements every time, and all the predefined variables can be used.
Predefined variables
When an event that triggers execution of certain Cypher queries is identified, information about the event, that is the information about the created, updated, or delted objects (nodes, relationships or both) in a single transaction are saved within a predifined variables.
Each event type creates different predefined variables:
Event type | Predefined variables |
---|---|
ON CREATE | createdVertices , createdEdges , createdObjects |
ON () CREATE | createdVertices |
ON --> CREATE | createdEdges |
ON UPDATE | setVertexProperties , setEdgeProperties , removedVertexProperties , removedEdgeProperties , setVertexLabels , removedVertexLabels , updatedVertices , updatedEdges , updatedObjects |
ON () UPDATE | setVertexProperties , removedVertexProperties , setVertexLabels , removedVertexLabels , updatedVertices |
ON --> UPDATE | setEdgeProperties , removedEdgeProperties , updatedEdges |
ON DELETE | deletedVertices , deletedEdges , deletedObjects |
ON () DELETE | deletedVertices |
ON --> DELETE | deletedEdges |
no event type specified | All predefined variables can be used. |
ON CREATE
createdVertices
List of all created nodes (vertices).
createdEdges
List of all created relationships (edges).
createdObjects
List of all created objects where each element is a map.
If the element contains a created node (vertex), it will be in the following format:
{
"event_type": "created_vertex",
"vertex": created_vertex_object
}
If the element contains a created relationship (edge), it will be in the following format:
{
"event_type": "created_edge",
"edge": created_edge_object
}
ON UPDATE
Setting an element to NULL
is counted as a removal.
The changes are looked at on the transaction level only. That means if the value of a property on the same object was changed multiple times, only one update will be generated. The same applies for changes to node labels.
setVertexProperties
List of all set node (vertex) properties.
Each element is in the following format:
{
"vertex": updated_vertex_object,
"key": property_that_was_updated,
"old": old_value_of_that_property,
"new": new_value_of_that_property
}
setEdgeProperties
List of all set relationship (edge) properties.
Each element is in the following format:
{
"edge": updated_vertex_object,
"key": property_that_was_updated,
"old": old_value_of_that_property,
"new": new_value_of_that_property
}
removedVertexProperties
List of all removed node (vertex) properties.
Each element is in the following format:
{
"vertex": updated_vertex_object,
"key": property_that_was_updated,
"old": old_value_of_that_property
}
removedEdgeProperties
List of all removed relationship (edge) properties.
Each element is in the following format:
{
"vertex": updated_vertex_object,
"key": property_that_was_updated,
"old": old_value_of_that_property
}
setVertexLabels
List of all set node (vertex) labels.
Each element is in the following format:
{
"label": label,
"vertices": list_of_updated_vertices
}
removedVertexLabels
List of all removed node (vertex) labels.
Each element is in the following format:
{
"label": label,
"vertices": list_of_updated_vertices
}
updatedVertices
List of updates consisting of set and removed properties, and set and removed labels on nodes (vertices).
updatedEdges
List of updates consisting of set and removed properties on relationships (edges).
updatedObjects
List of updates consisting of set and removed properties on relationships (edges) and nodes (vertices), and set and removed labels on nodes (vertices).
Elements of update predefined variables
If the element contains information about a set node (vertex) property, it's in the following format:
{
"event_type": "set_vertex_property",
"vertex": updated_vertex_object,
"key": property_that_was_updated,
"old": old_value_of_that_property,
"new": new_value_of_that_property
}
If the element contains information about a removed node (vertex) property, it's in the following format:
{
"event_type": "removed_vertex_property",
"vertex": updated_vertex_object,
"key": property_that_was_updated,
"old": old_value_of_that_property
}
If the element contains information about a set relationship (edge) property, it's in the following format:
{
"event_type": "set_edge_property",
"edge": updated_edge_object,
"key": property_that_was_updated,
"old": old_value_of_that_property,
"new": new_value_of_that_property
}
If the element contains information about a removed relationship (edge) property, it's in the following format:
{
"event_type": "removed_edge_property",
"edge": updated_edge_object,
"key": property_that_was_updated,
"old": old_value_of_that_property
}
If the element contains information about a set node (vertex) label, it's in the following format:
{
"event_type": "set_vertex_label",
"vertex": updated_vertex_object,
"label": label
}
If the element contains information about a removed node (vertex) label, it's in the following format:
{
"event_type": "removed_vertex_label",
"vertex": updated_vertex_object,
"label": label
}
ON DELETE
deletedVertices
List of all deleted (nodes) vertices.
deletedEdges
List of all deleted (relationships) edges.
deletedObjects
List of all deleted objects where each element is a map.
If the element contains a created node (vertex), it will be in the following format:
{
"event_type": "deleted_vertex",
"vertex": deleted_vertex_object
}
If the element contains a created relationship (edge), it will be in the following format:
{
"event_type": "deleted_edge",
"edge": deleted_edge_object
}
Statement execution phase
A trigger can execute its statements at a specified phase, before or after
Memgraph commits the transaction that triggered it. If the BEFORE COMMIT
option is
used, the trigger will execute its statements as part of that transaction before
it's committed. If the AFTER COMMIT
option is used, the trigger will execute
its statements asynchronously after that transaction is committed.
Execute statements
A trigger can execute any valid openCypher query. No specific constraints are imposed on the queries. The only way trigger queries (i.e. statements) differ from standard queries is that a trigger query may use predefined variables, which are based on the event type specified for the trigger.
Example triggers
An example of a trigger would be:
CREATE TRIGGER exampleTrigger1
ON () CREATE AFTER COMMIT EXECUTE
UNWIND createdVertices AS newNodes
SET newNodes.created = timestamp();
When a new node is created and the transaction is committed, the exampleTrigger1
will take the list of newly created nodes and for each new node set the property
created
to a timestamp value indicating the time of its creation.
A more complex example would be:
CREATE TRIGGER exampleTrigger2
ON UPDATE AFTER COMMIT EXECUTE
UNWIND updatedObjects AS updatedObject
WITH CASE
WHEN updatedObject.vertex IS NOT null THEN updatedObject.vertex
WHEN updatedObject.edge IS NOT null THEN updatedObject.edge
END AS object
SET object.updated_at = timestamp();
The query is more complex, so let's break it down:
CREATE TRIGGER exampleTrigger
: Creates the trigger and gives it a unique nameexampleTrigger
.ON UPDATE AFTER COMMIT EXECUTE
: Specifies what event will trigger the execution of Cypher statements. InexampleTrigger2
any update of any graph object will trigger the execution once the update event has been committed.UNWIND updatedObjects AS updatedObject
: If multiple objects were updated, unwind the list inside the predefined variable and go over each one.WITH CASE...
: TheCASE
expression checks what type of object was updated, a node (vertex) or a relationship (edge).SET object.updated_at = timestamp();
: Add anupdated_at
property to the object indicating when the action happened.
Create a trigger for Python query module
If you want a trigger to be activated by executing code from a Python query
module, you can call the query module from the trigger. In the example below,
the trigger will call query_module.new_edge(edge)
each time a new relationship
(edge) is created:
CREATE TRIGGER newEdge
ON CREATE BEFORE COMMIT EXECUTE
UNWIND createdEdges AS edge
CALL query_module.new_edge(edge) YIELD *;
Make sure your function accepts the proper Memgraph type, mgp.Edge
in this
case.
def new_edge(
context: mgp.ProcCtx,
edge: mgp.Edge
)
Memgraph Python API is defined by mgp.py
script, and in it, you can find all
supported types such as mgp.Edge
, mgp.Vertex
etc. If you want to explore the
API further, feel free to check the reference guide on Python
API.
Create a trigger for dynamic algorithms
Dynamic
algorithms
are often designed for dataset updates. With a trigger, you can ensure that any
dataset is up to date and consistent. In the sample code below, a trigger is set
to use MAGE pagerank_online
algorithm.
CREATE TRIGGER pagerank_trigger
BEFORE COMMIT
EXECUTE CALL pagerank_online.update(createdVertices, createdEdges, deletedVertices, deletedEdges)
YIELD node, rank
SET node.rank = rank;
In this case, all created or deleted objects are passed from the database transaction to the trigger. After each transaction that has created or deleted objects, the trigger will automatically execute the PageRank algorithm and update the rank property. This will ensure data consistency and lead to performance benefits.
Dropping a trigger
A trigger can be deleted by running the following query:
DROP TRIGGER trigger_name;
Trigger owner
The user who executes the CREATE TRIGGER
query is the owner of the trigger.
Authentication and authorization are not supported in Memgraph Community, thus
the owner is always Null
, and the privileges are not checked.
In Memgraph Enterprise, the privileges of the owner are used when executing Cypher statements, in other words, the execution of the statements will fail if the owner doesn't have the required privileges.
Triggers created by users logged in via SSO cannot be used beyond the session they were created in.
Trigger info
The following query will return information about all triggers:
SHOW TRIGGERS;
Information:
trigger name | statement | event type | phase | owner |
---|---|---|---|---|
Trigger name | Statement the trigger executes. | Event type that triggers the statement execution. | When is the trigger executed. | The trigger owner or Null . |