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
…) (#4325)
  • Loading branch information
vga91 authored Jan 15, 2025
1 parent 6228fae commit 4a99c98
Show file tree
Hide file tree
Showing 32 changed files with 199 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

`apoc.custom.list()` - provide a list of custom procedures/function registered
¦label:procedure[]
¦label:apoc-extended[]
¦label:apoc-full[]
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

`apoc.custom.list()` - provide a list of custom procedures/function registered
¦label:procedure[]
¦label:apoc-extended[]
¦label:apoc-full[]
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

`apoc.custom.list()` - provide a list of custom procedures/function registered
¦label:procedure[]
¦label:apoc-extended[]
¦label:apoc-full[]
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

`apoc.custom.list()` - provide a list of custom procedures/function registered
¦label:procedure[]
¦label:apoc-extended[]
¦label:apoc-full[]
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

`apoc.custom.list()` - provide a list of custom procedures/function registered
¦label:procedure[]
¦label:apoc-extended[]
¦label:apoc-full[]
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

`apoc.custom.list()` - provide a list of custom procedures/function registered
¦label:procedure[]
¦label:apoc-extended[]
¦label:apoc-full[]
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-full[]
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-full[]
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
Expand Up @@ -2,7 +2,7 @@
= apoc.agg.multiStats
:description: This section contains reference documentation for the apoc.agg.multiStats function.

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

[.emphasis]
apoc.agg.multiStats(nodeOrRel, keys) - Return a multi-dimensional aggregation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= apoc.convert.fromYaml
:description: This section contains reference documentation for the apoc.convert.fromYaml function.

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

[.emphasis]
apoc.convert.fromYaml(value, $config) - Deserializes the YAML string to Neo4j value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= apoc.custom.dropAll
:description: This section contains reference documentation for the apoc.custom.dropAll procedure.

label:procedure[] label:apoc-extended[]
label:procedure[] label:apoc-full[]

[.emphasis]
Eventually drops all previously added custom procedures/functions and returns info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= apoc.custom.dropFunction
:description: This section contains reference documentation for the apoc.custom.dropFunction procedure.

label:procedure[] label:apoc-extended[]
label:procedure[] label:apoc-full[]

[.emphasis]
Eventually drops the targeted custom function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= apoc.custom.dropProcedure
:description: This section contains reference documentation for the apoc.custom.dropProcedure procedure.

label:procedure[] label:apoc-extended[]
label:procedure[] label:apoc-full[]

[.emphasis]
Eventually drops the targeted custom procedure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= apoc.custom.installFunction
:description: This section contains reference documentation for the apoc.custom.installFunction procedure.

label:procedure[] label:apoc-extended[]
label:procedure[] label:apoc-full[]

[.emphasis]
Eventually registers a custom cypher function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= apoc.custom.installProcedure
:description: This section contains reference documentation for the apoc.custom.installProcedure procedure.

label:procedure[] label:apoc-extended[]
label:procedure[] label:apoc-full[]

[.emphasis]
Eventually registers a custom cypher procedure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= apoc.custom.show
:description: This section contains reference documentation for the apoc.custom.show procedure.

label:procedure[] label:apoc-extended[]
label:procedure[] label:apoc-full[]

[.emphasis]
Provides a list of custom procedures/function registered
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= apoc.import.arrow
:description: This section contains reference documentation for the apoc.import.arrow procedure.

label:procedure[] label:apoc-extended[]
label:procedure[] label:apoc-full[]

[.emphasis]
apoc.import.arrow(input, $config) - Imports arrow from the provided arrow file or byte array
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-full[]

== 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-full[]

== 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 @@ -2,7 +2,7 @@
= apoc.util.hashCode
:description: This section contains reference documentation for the apoc.util.hashCode function.

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

[.emphasis]
apoc.util.hashCode(value) - Returns the java.lang.Object#hashCode() of the value
Expand Down
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 4a99c98

Please sign in to comment.