为了准备GraphConnect,以及为那里的黑客马拉松做一个主意,我最近需要研究如何在Neo4j中执行触发器。
在本文中,我们将介绍什么是触发器,如何使用它们进行流数据加载,最后,我们将详细介绍它们的工作原理。

如果您以前从未使用过触发器,则触发器是一种数据库方法,它在事件发生时运行某些操作。 您可以使用它们来使数据库对事件做出反应,而不是被动地接受数据,这使它们非常适合流式传输数据,流式数据是一组事件。
触发器需要两部分:
- 触发条件(触发器应触发哪个事件?)
- 触发器动作(触发器触发时该怎么办?)
Neo4j中的触发器可通过“ Cypher上的Awesome Procedures(APOC)”获得,您可以在此处找到有关它们的文档。 让我们跳进去。
我不时使用APOC触发器进行数据加载。 想象一下,随着时间的流逝,流入neo4j的记录代表了社交网络中的朋友关系:
创建(:FriendRecord {p1:“ David”,p2:“ Mark”});
创建(:FriendRecord {p1:“ Mark”,p2:“ Susan”});
创建(:FriendRecord {p1:“鲍勃”,p2:“苏珊”});
这些可能来自外部应用程序或像Kafka这样的消息传递队列。
如果这是批量数据,人们可能会将它们批量化为CSV并编写一些LOAD CSV代码,从而从一开始就将数据加载到适当的图形结构中。 但是,对于连续到达数据的流设置而言,这将不起作用。
将重载(以平凡的格式)与重新格式化分开也是很重要的,因为如果数据来自Kafka上的其他某个应用程序,则该应用程序将不知道或不在乎您的图形模型是什么。
因此,假设您的数据库正在不断获取这些“ FriendRecord”节点,但是真正想要的是一个合适的图形,如下所示:
(:Person {名称:“ David”})-[:FRIENDS]->(:Person {名称:“ Mark”})
这就是触发器的用例-流图加载和转换! 我们走吧。
首先,您必须将APOC安装到正在使用的某些Neo4j数据库中。 然后,APOC要求为了使用触发器,必须设置:
apoc.trigger.enabled = true
在您的neo4j.conf中,所以不要忘记这样做。

这是我们将要使用的触发器。 这既定义了触发条件,又定义了触发动作。
致电apoc.trigger.add('loadFriendRecords',
“ UNWIND apoc.trigger.nodesByLabel({assignedLabels},'FriendRecord')AS节点
合并(p1:Person {name:node.p1})
合并(p2:Person {name:node.p2})
合并(p1)-[:朋友]->(p2)
DETACH DELETE节点”,
{phase:'after'});
让我们来探讨一下这些论点。 第一个参数“ loadFriendsRecord”是触发器的名称。 以后我们可以使用该名称询问触发器的状态,或者在需要时将其删除。 第二个参数是密码查询,它是触发条件和操作。 那就是这里所有的肉:
- UNWIND apoc.trigger.nodesByLabel部分获取带有标签“ FriendRecord”的节点。 我们将在下面深入解释其工作原理。
- 映射中的“ assignedLabels”部分指示在将标签分配给节点或首次创建标签时触发条件。
- 取消该列表,现在我们的查询包含所有最近创建的FriendRecord节点。 查询的其余部分仅指定如何处理它们。 我们将合并2个新的Person节点,进行连接,然后删除原始的FriendRecord节点,这就是将我们从传入的记录转换为目标图形格式的原因。
最后,第三个参数{phase:’after’}允许您控制何时触发操作。 您的选择是“之前”,“之后”或“回滚”,它们与Neo4j中事务的生命周期可能性相对应。 因为我的触发器想要修改数据,所以该阶段必须在“之后”。 (尝试在甚至提交事务之前执行该delete语句将不起作用)。 如果您需要在输入新的PersonRecord之前执行一些操作,则需要“在此之前”。 而且,如果您想对创建PersonRecord失败进行某些操作,则可以使用“回滚”。
Neo4j核心数据库包括用于“事务事件处理程序”的工具。 Neo4j插件可以创建事务事件处理程序,并在数据库提交事务时调用。 这种基本功能使任何软件都可以观察数据流过时发生的情况。
APOC抢断交易
在APOC中启用触发器时,这将导致APOC向数据库注册事务事件处理程序,并开始侦听所有这些更改。 没有任何触发器,此侦听器将不执行任何操作。
注册触发器时,它带有一个“选择器”。 这就是{assignedLabels}部分。 如上所述,每个触发器都有一个“阶段”。
触发针对交易执行
因此,APOC维护一个触发器列表,每个触发器都有一个选择器,一个阶段和一个密码查询。 并且它具有事务事件处理程序。 其余的很简单:每次交易进入Neo4j时,APOC都会运行相关的触发器。
请记住,每个事务都有三个可能的阶段:之前,之后和回滚。 APOC获取这些事件中的每一个,找出在该阶段要执行的触发器,然后运行您指定的密码。 在运行此查询之前,它会在查询中为地图设置一组特殊的参数。 这些参数提供有关正在执行的事务的详细信息,例如添加和删除了哪些节点等等。
因此,执行的密码查询几乎可以完全访问事务中的数据!
过滤掉相关数据
最后要理解的部分是我们原始触发器中的这一部分:
apoc.trigger.nodesByLabel({assignedLabels},'FriendRecord')
这是触发器的核心,因为它定义了我们希望代码何时执行。 每当为新节点分配FriendRecord标签!
第一个参数是一个映射,可以包含assignedLabels,removeLabel,removeNodeProperties或这三者的任意组合。 该地图对于初学者可能会造成混淆,因为请注意,地图键没有任何值。 他们不需要它们。 APOC只关心密钥是否在地图中。
在最后一步中,我们解释了执行触发器时,它会传递很多事务状态。 在这种状态下,此函数可以非常简单地仅拉出分配了“ FriendRecord”标签的节点。 那将成为传递给UNWIND的数组,其余就是您的代码。
我们只介绍触发器在这里可以执行的一小部分,以使您领会到特定于此用例的情况。 上面,我们讨论了不同的生命周期阶段(之前/之后/回滚)以及不同的选择器类型(分配的节点属性,分配的关系属性,删除的节点标签等)。
这些可以非常灵活地组合在一起,以在neo4j,数据质量清除以及相关事务中实现各种业务逻辑。 我们很想在Neo4j社区论坛上听听其他人如何使用它们,所以请顺便告诉我们。
看看你自己
因为APOC是开源的,所以您当然可以随时了解它的完成方式。