Skip to content

Commit

Permalink
[NOID] Fixes #4263: Adds docs for apoc triggers helper functions (#4311)
Browse files Browse the repository at this point in the history
* Revert "Removed org.apache.commons.collections from OpenAI (#4304)" (#4305)

This reverts commit 7e3bfb7.

* Fixes #4244: Make apoc.dv.* procedures work in clusters (#4281)

* Fixes #4244: Make apoc.dv.* procedures work in clusters

* added procs to extended*.txt

* fix tests

* cleanup

* Fixes #4263: Adds docs for apoc triggers helper functions

* Update apoc.trigger.toNode.adoc

* Update apoc.trigger.toRelationship.adoc
  • Loading branch information
vga91 committed Jan 15, 2025
1 parent 6228fae commit 7a66a42
Show file tree
Hide file tree
Showing 16 changed files with 183 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
¦xref::overview/apoc.trigger/apoc.trigger.nodesByLabel.adoc[apoc.trigger.nodesByLabel icon:book[]] +

``
`apoc.trigger.nodesByLabel(labelEntries, label)` - function to filter labelEntries by label, to be used within a trigger kernelTransaction with `$assignedLabels`, `$removedLabels`, `$assigned/removedNodeProperties`.
¦label:function[]
¦label:apoc-full[]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
¦xref::overview/apoc.trigger/apoc.trigger.propertiesByKey.adoc[apoc.trigger.propertiesByKey icon:book[]] +

``
`apoc.trigger.propertiesByKey(propertyEntries, key)` - function to filter propertyEntries by property-key, to be used within a trigger kernelTransaction with `$assignedNode/RelationshipProperties` and `$removedNode/RelationshipProperties`. Returns [`old`,`new`,`key`,`node`,`relationship`].
¦label:function[]
¦label:apoc-full[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
¦signature
¦apoc.trigger.nodesByLabel(labelEntries :: ANY?, label :: STRING?) :: (LIST? OF ANY?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
¦xref::overview/apoc.trigger/apoc.trigger.toNode.adoc[apoc.trigger.toNode icon:book[]] +

`apoc.trigger.toNode(node, removedLabels, removedNodeProperties)` - function to rebuild a node as a virtual one, to be used in triggers with a not 'afterAsync' phase.
¦label:function[]
¦label:apoc-extended[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
¦type¦qualified name¦signature¦description
¦function¦apoc.trigger.nodesByLabel¦apoc.trigger.nodesByLabel(labelEntries :: ANY?, label :: STRING?) :: (LIST? OF ANY?)¦
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
¦signature
¦apoc.trigger.nodesByLabel(labelEntries :: ANY?, label :: STRING?) :: (LIST? OF ANY?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
¦xref::overview/apoc.trigger/apoc.trigger.toRelationship.adoc[apoc.trigger.toRelationship icon:book[]] +

`apoc.trigger.toRelationship(rel, removedRelationshipProperties)` - function to rebuild a relationship as a virtual one, to be used in triggers with a not 'afterAsync' phase.
¦label:function[]
¦label:apoc-extended[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
¦type¦qualified name¦signature¦description
¦function¦apoc.trigger.nodesByLabel¦apoc.trigger.nodesByLabel(labelEntries :: ANY?, label :: STRING?) :: (LIST? OF ANY?)¦
1 change: 1 addition & 0 deletions docs/asciidoc/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ include::partial$generated-documentation/nav.adoc[]
* xref:background-operations/index.adoc[]
** xref::background-operations/periodic-background.adoc[]
** xref::background-operations/triggers.adoc[]
** xref::background-operations/apoc-load-directory-async.adoc[]
* xref:database-introspection/index.adoc[]
** xref::database-introspection/meta.adoc[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ include::example$generated-documentation/apoc.trigger.stop.adoc[]
include::example$generated-documentation/apoc.trigger.start.adoc[]
include::example$generated-documentation/apoc.trigger.show.adoc[]
include::example$generated-documentation/apoc.trigger.list.adoc[]

|===


Expand Down Expand Up @@ -53,12 +54,13 @@ Otherwise, it has the value `-1`.
You can use these helper functions to extract nodes or relationships by label/relationship-type or updated property key.

.Helper Functions
[cols="5m,5"]
[separator=¦,opts=header,cols="5,1m,1m"]
|===
| apoc.trigger.nodesByLabel($assignedLabels/$assignedNodeProperties,'Label') | function to filter entries by label, to be used within a trigger statement with `$assignedLabels` and `$removedLabels`
| apoc.trigger.propertiesByKey($assignedNodeProperties,'key') | function to filter propertyEntries by property-key, to be used within a trigger statement with $assignedNode/RelationshipProperties and $removedNode/RelationshipProperties. Returns [{old,[new],key,node,relationship}]
| apoc.trigger.toNode(node, $removedLabels, $removedNodeProperties) | function to rebuild a node as a virtual, to be used in triggers with a not 'afterAsync' phase
| apoc.trigger.toRelationship(rel, $removedRelationshipProperties) | function to rebuild a relationship as a virtual, to be used in triggers with a not 'afterAsync' phase
¦Qualified Name¦Type¦Release
include::example$generated-documentation/apoc.trigger.nodesByLabel.adoc[]
include::example$generated-documentation/apoc.trigger.propertiesByKey.adoc[]
include::example$generated-documentation/apoc.trigger.toNode.adoc[]
include::example$generated-documentation/apoc.trigger.toRelationship.adoc[]
|===

The 3rd parameter of the `apoc.trigger.install()` is a map `{phase: PHASE}`, where `PHASE` is a string which can have one of the following values:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

= apoc.trigger.toNode
:description: This section contains reference documentation for the apoc.trigger.toNode function.

label:function[] label:apoc-extended[]

== Signature

[source]
----
apoc.trigger.toNode(node :: NODE, removedLabels :: MAP, removedNodeProperties :: MAP) :: RELATIONSHIPH
----

== Input parameters
[.procedures, opts=header]
|===
| Name | Type | Default
|node|NODE|null
|removedLabels|MAP|null
|removedNodeProperties|MAP|null
|===

[[usage-apoc.trigger.nodesByLabel]]
== Usage Examples
include::partial$usage/apoc.trigger.toNode.adoc[]

xref::background-operations/triggers.adoc[More documentation of apoc.trigger.toNode,role=more information]

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

= apoc.trigger.toRelationship
:description: This section contains reference documentation for the apoc.trigger.toRelationship function.

label:function[] label:apoc-extended[]

== Signature

[source]
----
apoc.trigger.toRelationship(rel :: RELATIONSHIP, removedRelationshipProperties :: MAP) :: RELATIONSHIP
----

== Input parameters
[.procedures, opts=header]
|===
| Name | Type | Default
|rel|RELATIONSHIP|null
|removedRelationshipProperties|MAP|null
|===

[[usage-apoc.trigger.nodesByLabel]]
== Usage Examples
include::partial$usage/apoc.trigger.toRelationship.adoc[]

xref::background-operations/triggers.adoc[More documentation of apoc.trigger.toNode,role=more information]

Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ create constraint on (p:Person)
assert p.id is unique;
----

This function is used inside a xref::overview/apoc.trigger/apoc.trigger.add.adoc[] Cypher statement.
This function is used inside a xref::overview/apoc.trigger/apoc.trigger.install.adoc[] Cypher statement.

We can use it to conditionally run Cypher statements when labels are added or removed or when properties are added or removed.
For example, we add an `id` property to all `Person` nodes that is the lower case value of the `name` property of that node, by defining the following trigger:

[source,cypher]
----
CALL apoc.trigger.add(
CALL apoc.trigger.install(
'neo4j',
'lowercase',
'UNWIND apoc.trigger.nodesByLabel($assignedLabels,"Person") AS n
SET n.id = toLower(n.name)',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
This function is used inside a xref::overview/apoc.trigger/apoc.trigger.add.adoc[] Cypher statement.
This function is intended to be used within an xref::overview/apoc.trigger/apoc.trigger.install.adoc[] Cypher statement.

We can use it to conditionally run Cypher statements when properties are added or removed.
For example, we can connect nodes with a `genre` property to a `Genre` node, with the following trigger:

[source,cypher]
----
CALL apoc.trigger.add(
CALL apoc.trigger.install(
'neo4j',
'triggerTest',
'UNWIND apoc.trigger.propertiesByKey($assignedNodeProperties, "genre") as prop
WITH prop.node as n
Expand Down
46 changes: 46 additions & 0 deletions docs/asciidoc/modules/ROOT/partials/usage/apoc.trigger.toNode.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
This function is intended to be used within an xref::overview/apoc.trigger/apoc.trigger.install.adoc[] Cypher statement.

If we want to create a 'before' or 'after' trigger query using `$deletedNodes`, and retrieve entity information such as labels and/or properties, we cannot use the classic Cypher functions labels() and properties().
Instead, we have to leverage virtual nodes through the function `apoc.trigger.toNode(node, $removedLabels, $removedNodeProperties)`.

For example, to create a new `Report` node with a list of deleted node IDs and all the labels retrieved for each deleted node, we can execute:
[source,cypher]
----
CALL apoc.trigger.install(
'neo4j', 'myTrigger',
"UNWIND $deletedNodes as deletedNode
WITH apoc.trigger.toNode(deletedNode, $removedLabels, $removedNodeProperties) AS deletedNode
CALL apoc.merge.node(
['Report'],
{labels: apoc.node.labels(deletedNode)},
{created: datetime()},
{updated: datetime()}
) YIELD node AS report
WITH report, deletedNode
SET report.deletedIds = coalesce(report.deletedIds, [])+[id(deletedNode)]" ,
{phase:'before'}
);
----

Now, let's create and delete a `Movie` node:

[source,cypher]
----
CREATE (:Movie {title: "The White Tiger"});
MATCH (movie:Movie {title: "The White Tiger"}) DELETE movie;
----

Finally, let's check the `Report` node:

[source,cypher]
----
MATCH (report:Report {labels: ['Movie']})
RETURN report;
----

.Results
[opts="header"]
|===
| report
| (:Report {"created": "2024-12-12T08:33:27.188000000Z", "deletedIds": [12], "labels": ["Movie"]})
|===
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
This function is intended to be used within an xref::overview/apoc.trigger/apoc.trigger.install.adoc[] Cypher statement.

If we want to create a 'before' or 'after' trigger query using `$deletedRelationships`, and retrieve entity information such as the type and/or properties, we cannot use the classic Cypher functions type() and properties().
Instead, we have to leverage virtual relationships through the function `apoc.trigger.toRelationship(rel, $removedRelationshipProperties)`.

For example, to create a new `Report` node with a list of deleted relationship IDs and the type retrieved for each deleted relationship, we can execute:
[source,cypher]
----
CALL apoc.trigger.install(
'neo4j', 'myTrigger',
"UNWIND $deletedRelationships as deletedRel
WITH apoc.trigger.toRelationship(deletedRel, $removedRelationshipProperties) AS deletedRel
CALL apoc.merge.node(
['Report'],
{type: apoc.rel.type(deletedRel)},
{created: datetime()},
{updated: datetime()}
) YIELD node AS report
WITH report, deletedRel
SET report.deletedIds = coalesce(report.deletedIds, [])+[id(deletedRel)]" ,
{phase:'before'}
);
----

Now, let's create and delete a `IN_GENRE` relationship between a `Movie` node and a `Genre` node:

[source,cypher]
----
MERGE (movie:Movie {title: "The White Tiger"})
MERGE (genre:Genre {name: "Triller"})
MERGE (movie)-[IN_GENRE]->(genre);
MATCH (movie:Movie {title: "The White Tiger"})-[r:IN_GENRE]->(genre:Genre {name: "Triller"}) DELETE r;
----

Finally, let's check the `Report` node:

[source,cypher]
----
MATCH (report:Report {labels: ['IN_GENRE']})
RETURN report;
----

.Results
[opts="header"]
|===
| report
| (:Report {"created": "2024-12-12T08:33:27.188000000Z", "deletedIds": [12], "type": "IN_GENRE"})
|===

0 comments on commit 7a66a42

Please sign in to comment.