Neo4j APOC assignedRelationshipProperties、removedRelationshipProperties 触发器和 apoc.index.in
Neo4j APOC assignedRelationshipProperties, removedRelationshipProperties triggers and apoc.index.in
我使用 Neo4j 3.3.5 Community Edition
和 APOC apoc-3.3.0.2-all.jar
我有触发器允许我 add/remove 来自特定关系的所有属性 to/from 手动索引:
CALL apoc.trigger.add('HAS_VALUE_ON_CREATED_RELATIONSHIPS_TRIGGER',
'UNWIND {createdRelationships} AS r
MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic)
CALL apoc.index.addRelationship(r, keys(r)) RETURN count(*)', {phase:'after'})
CALL apoc.trigger.add('HAS_VALUE_ON_DELETED_RELATIONSHIPS_TRIGGER',
\"UNWIND {deletedRelationships} AS r
MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic)
CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)\", {phase:'after'})
我的业务逻辑还可以引入新属性或从现有关系中删除现有属性,因此我认为为了使我的索引保持最新我还应该使用另外两个语句,例如:
assignedRelationshipProperties
removedRelationshipProperties
我说的对吗?如果是这样,您能否展示如何使用它们来从 MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic)
关系的索引中添加新触发器和 update/remove 属性?
更新 #1
我已经验证了答案部分提供的解决方案,但不幸的是它不起作用。请参阅下面的详细信息:
我创建了以下触发器:
CALL apoc.trigger.add('TEST_TRIGGER', "UNWIND keys({assignedRelationshipProperties}) AS key
UNWIND {assignedRelationshipProperties}[key] AS map
WITH map
WHERE type(map.relationship) = 'LIVES_IN'
CALL apoc.index.addRelationship(map.relationship, keys(map.relationship))
RETURN count(*)", {phase:'before'})
已通过 CALL apoc.trigger.list()
验证触发器是否存在
创建以下节点和关系:
CREATE (p:Person) return p
CREATE (c:City) return c
MATCH (p:Person), (c:City) CREATE (p)-[r:LIVES_IN]->(c) RETURN type(r)
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
quthe ery returns 空结果,目前还可以。
分配关系新 属性 time
with value = 10
:
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 10 RETURN r
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
查询成功returns预期的Person
节点
现在,我重新分配了 time
属性 另一个值 = 11
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 11 RETURN r
再次尝试通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:11') YIELD node AS person
RETURN person
查询 returns 两者都是空结果..
为什么 属性 更改后索引没有更新?
更新#2
我创建了以下触发器:
CALL apoc.trigger.add('HAS_VALUE_ON_ASSIGNED_RELATIONSHIP_PROPERTIES_TRIGGER',
"UNWIND apoc.trigger.propertiesByKey({assignedRelationshipProperties}, 'time') AS prop WITH prop.relationship as r
CALL apoc.index.addRelationship(r, keys(r))
RETURN count(*)", {phase:'after'})
已通过 CALL apoc.trigger.list()
验证触发器是否存在
创建以下节点和关系:
CREATE (p:Person) return p
CREATE (c:City) return c
MATCH (p:Person), (c:City) CREATE (p)-[r:LIVES_IN]->(c) RETURN type(r)
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
查询 returns 空结果,目前没问题。
分配关系新 属性 time
with value = 10
:
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 10 RETURN r
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
查询成功returns预期的Person
节点
现在,我重新分配了 time
属性 另一个值 = 11
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 11 RETURN r
再次尝试通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:11') YIELD node AS person
RETURN person
查询 returns 两者都是空结果..
因此,这种方法 运行 解决了与我之前在上面描述的相同的问题。另一个缺点是我需要指定确切的键名——在本例中为 time
。但是我对某些键不感兴趣,而是对 HAS_VALUE_ON
关系中所有键的 add/update/delete 感兴趣。
assignedRelationshipProperties
非常棘手。该参数的结构为Map<String, List<Map<String, Object>>>
.
其中,第一个String
是属性的键,列表元素是具有以下键的映射:
- key : 属性
的键
- old:旧值(如果有的话)
- new : 分配给 属性
的新值
- 关系:所讨论的关系
为了更加直观,调试格式的参数如下所示:
对于您的特定用例,更新关系 属性 特定关系类型更新的 lucene 索引,您可以使用以下查询:
CALL apoc.trigger.add('test-rel-trigger',
'UNWIND keys({assignedRelationshipProperties}) AS key
UNWIND {assignedRelationshipProperties}[key] AS map
WITH map WHERE type(map.relationship) = "HAS_VALUE_ON"
CALL apoc.index.addRelationship(map.relationship, keys(map.relationship)) RETURN count(*)'
, {phase:'before'})
至于删除,因为您索引了完整的属性图,我相信您可以将 assignedRelationshipProperties
替换为 removedRelationshipProperties
有专门的帮助函数来使用这些函数,文档中解释了这些函数可以访问 nodes/rels 或这些数据结构的属性:
参见:https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_triggers
Table 4. 辅助函数
apoc.trigger.nodesByLabel({assignedLabels/assignedNodeProperties},'Label')
按标签过滤标签条目的函数,用于 {assignedLabels}
和 {removedLabels}
的触发器语句中
{phase:'before/after/rollback'}
returns 之前和新的触发信息
apoc.trigger.propertiesByKey({assignedNodeProperties},'key')
函数通过 属性 键过滤 属性 条目,在 {assignedNode/RelationshipProperties}
和 {removedNode/RelationshipProperties}
的触发器语句中使用。
Returns [{old,[new],key,node,relationship}]
我使用 Neo4j 3.3.5 Community Edition
和 APOC apoc-3.3.0.2-all.jar
我有触发器允许我 add/remove 来自特定关系的所有属性 to/from 手动索引:
CALL apoc.trigger.add('HAS_VALUE_ON_CREATED_RELATIONSHIPS_TRIGGER',
'UNWIND {createdRelationships} AS r
MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic)
CALL apoc.index.addRelationship(r, keys(r)) RETURN count(*)', {phase:'after'})
CALL apoc.trigger.add('HAS_VALUE_ON_DELETED_RELATIONSHIPS_TRIGGER',
\"UNWIND {deletedRelationships} AS r
MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic)
CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)\", {phase:'after'})
我的业务逻辑还可以引入新属性或从现有关系中删除现有属性,因此我认为为了使我的索引保持最新我还应该使用另外两个语句,例如:
assignedRelationshipProperties
removedRelationshipProperties
我说的对吗?如果是这样,您能否展示如何使用它们来从 MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic)
关系的索引中添加新触发器和 update/remove 属性?
更新 #1
我已经验证了答案部分提供的解决方案,但不幸的是它不起作用。请参阅下面的详细信息:
我创建了以下触发器:
CALL apoc.trigger.add('TEST_TRIGGER', "UNWIND keys({assignedRelationshipProperties}) AS key
UNWIND {assignedRelationshipProperties}[key] AS map
WITH map
WHERE type(map.relationship) = 'LIVES_IN'
CALL apoc.index.addRelationship(map.relationship, keys(map.relationship))
RETURN count(*)", {phase:'before'})
已通过 CALL apoc.trigger.list()
创建以下节点和关系:
CREATE (p:Person) return p
CREATE (c:City) return c
MATCH (p:Person), (c:City) CREATE (p)-[r:LIVES_IN]->(c) RETURN type(r)
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
quthe ery returns 空结果,目前还可以。
分配关系新 属性 time
with value = 10
:
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 10 RETURN r
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
查询成功returns预期的Person
节点
现在,我重新分配了 time
属性 另一个值 = 11
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 11 RETURN r
再次尝试通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:11') YIELD node AS person
RETURN person
查询 returns 两者都是空结果..
为什么 属性 更改后索引没有更新?
更新#2
我创建了以下触发器:
CALL apoc.trigger.add('HAS_VALUE_ON_ASSIGNED_RELATIONSHIP_PROPERTIES_TRIGGER',
"UNWIND apoc.trigger.propertiesByKey({assignedRelationshipProperties}, 'time') AS prop WITH prop.relationship as r
CALL apoc.index.addRelationship(r, keys(r))
RETURN count(*)", {phase:'after'})
已通过 CALL apoc.trigger.list()
创建以下节点和关系:
CREATE (p:Person) return p
CREATE (c:City) return c
MATCH (p:Person), (c:City) CREATE (p)-[r:LIVES_IN]->(c) RETURN type(r)
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
查询 returns 空结果,目前没问题。
分配关系新 属性 time
with value = 10
:
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 10 RETURN r
试图通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
查询成功returns预期的Person
节点
现在,我重新分配了 time
属性 另一个值 = 11
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 11 RETURN r
再次尝试通过索引查询访问它:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:11') YIELD node AS person
RETURN person
查询 returns 两者都是空结果..
因此,这种方法 运行 解决了与我之前在上面描述的相同的问题。另一个缺点是我需要指定确切的键名——在本例中为 time
。但是我对某些键不感兴趣,而是对 HAS_VALUE_ON
关系中所有键的 add/update/delete 感兴趣。
assignedRelationshipProperties
非常棘手。该参数的结构为Map<String, List<Map<String, Object>>>
.
其中,第一个String
是属性的键,列表元素是具有以下键的映射:
- key : 属性 的键
- old:旧值(如果有的话)
- new : 分配给 属性 的新值
- 关系:所讨论的关系
为了更加直观,调试格式的参数如下所示:
对于您的特定用例,更新关系 属性 特定关系类型更新的 lucene 索引,您可以使用以下查询:
CALL apoc.trigger.add('test-rel-trigger',
'UNWIND keys({assignedRelationshipProperties}) AS key
UNWIND {assignedRelationshipProperties}[key] AS map
WITH map WHERE type(map.relationship) = "HAS_VALUE_ON"
CALL apoc.index.addRelationship(map.relationship, keys(map.relationship)) RETURN count(*)'
, {phase:'before'})
至于删除,因为您索引了完整的属性图,我相信您可以将 assignedRelationshipProperties
替换为 removedRelationshipProperties
有专门的帮助函数来使用这些函数,文档中解释了这些函数可以访问 nodes/rels 或这些数据结构的属性:
参见:https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_triggers
Table 4. 辅助函数
apoc.trigger.nodesByLabel({assignedLabels/assignedNodeProperties},'Label')
按标签过滤标签条目的函数,用于 {assignedLabels}
和 {removedLabels}
的触发器语句中
{phase:'before/after/rollback'}
returns 之前和新的触发信息
apoc.trigger.propertiesByKey({assignedNodeProperties},'key')
函数通过 属性 键过滤 属性 条目,在 {assignedNode/RelationshipProperties}
和 {removedNode/RelationshipProperties}
的触发器语句中使用。
Returns [{old,[new],key,node,relationship}]