Neo4J触发器记录删除节点至CSV报错,寻求技术帮助
解决Neo4j删除节点触发器报错
Neo.ClientError.Transaction.TransactionHookFailed的问题 问题背景
你在Windows环境下使用Neo4j 3.3.1搭配APOC 3.3.1插件,想要实现节点或关系删除时自动把详情导出到CSV文件。目前删除关系的触发器已经正常工作——通过创建虚拟节点记录关系的起始/结束节点UUID、关系类型,再导出到CSV;但删除节点的触发器执行时却抛出Neo.ClientError.Transaction.TransactionHookFailed错误,日志提示“Node with id XXX has been deleted in this transaction”,可实际查询节点却发现它还存在。
问题原因
问题出在你删除节点的触发器逻辑里:在before阶段的触发器中,你直接引用了已经被标记为待删除的节点对象(del)来提取uuid和标签。虽然处于before阶段节点还没被物理删除,但Neo4j的事务钩子已经把它标记为待删除状态,后续再访问这个节点对象的属性就会触发冲突检测,导致报错。
而删除关系的触发器能正常运行,是因为你访问的是关系关联的起始/结束节点(这些节点并没有被删除),而非待删除的关系对象本身的属性,所以没触发同样的冲突。
解决方案
修改删除节点的触发器语句,先把待删除节点需要的属性和标签提取到独立变量里,再用这些变量创建虚拟节点,避免直接引用已标记删除的节点对象:
call apoc.trigger.add("deletingNodes", "UNWIND {deletedNodes} as del WITH del, del.uuid as nodeUuid, labels(del) as nodeLabels CALL apoc.create.vNode(['Record'], {uuid:nodeUuid, nodeLabels:nodeLabels}) YIELD node as r WITH r, collect(r) as rs, 'D:/export/nodedeltest.cql' as filename CALL apoc.when(size(rs) > 0, 'call apoc.export.csv.data(rs,[],filename,{quotes:false,useTypes:false}) YIELD rows RETURN rows', '', {rs:rs,filename:filename}) YIELD value RETURN value", {phase:"before"})
验证方法
- 先执行上面修改后的语句创建触发器
- 运行你之前的删除节点测试查询
- 查看
D:/export/nodedeltest.cql文件是否正常生成,同时确认触发器不再抛出错误
额外提示
- 一定要保持
phase:"before":如果改成after阶段,节点已经被物理删除,你就没法提取它的属性和标签了 - 如果你的节点没有
uuid属性,可以换成节点ID来记录:把del.uuid as nodeUuid改成id(del) as nodeId,对应虚拟节点的属性也改成{nodeId:nodeId, nodeLabels:nodeLabels}
内容的提问来源于stack exchange,提问作者drwalter
相关产品推荐
相关产品推荐

