Neo4j APOC分配的RelationshipProperties、removedRelationshipProperties触发器和APOC.index.in
我使用带有APOC-3.3.0.2-all.jar的Neo4j 3.3.5社区版 我有一些触发器,可以将特定关系中的所有属性添加到手动索引或从手动索引中删除:Neo4j APOC分配的RelationshipProperties、removedRelationshipProperties触发器和APOC.index.in,neo4j,cypher,neo4j-apoc,Neo4j,Cypher,Neo4j Apoc,我使用带有APOC-3.3.0.2-all.jar的Neo4j 3.3.5社区版 我有一些触发器,可以将特定关系中的所有属性添加到手动索引或从手动索引中删除: CALL apoc.trigger.add('HAS_VALUE_ON_CREATED_RELATIONSHIPS_TRIGGER', 'UNWIND {createdRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic) CALL
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
我说得对吗?如果是这样,请说明如何使用这两种方法来添加新触发器和更新/删除匹配d:Decision-[r:HAS_VALUE_ON]->ch:Characteristic relationship索引中的属性
更新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.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'})
通过调用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)
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
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:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
QUERY返回空结果,目前还可以
赋值关系值为10的新属性时间:
试图通过索引查询访问它:
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:10') YIELD node AS person
RETURN person
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:10') YIELD node AS person
RETURN person
查询成功返回预期的人员节点
现在,我重新分配了时间属性另一个值=11
再次尝试通过索引查询访问它:
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
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
查询将为它们返回空结果
为什么属性更改后索引没有更新
更新2
我创建了以下触发器:
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.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'})
通过调用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)
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
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:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
查询返回空结果,目前还可以
赋值关系值为10的新属性时间:
试图通过索引查询访问它:
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:10') YIELD node AS person
RETURN person
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:10') YIELD node AS person
RETURN person
查询成功返回预期的人员节点
现在,我重新分配了时间属性另一个值=11
再次尝试通过索引查询访问它:
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
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
查询将为它们返回空结果
因此,这种方法遇到了与我前面描述的相同的问题。另一个缺点是,我需要指定确切的密钥名——在本例中是时间。但我对某些键不感兴趣,而是对HAS_VALUE_ON关系中所有键的添加/更新/删除感兴趣。分配的关系属性相当棘手。此参数的结构是Map
其中,第一个字符串是属性的键,列表元素是具有以下键的映射:
键:属性的键
旧值:旧值(如果有)
新建:指定给特性的新值
关系:有问题的关系
为了更直观,以下是调试格式中的参数:
对于您的特定用例,更新特定关系类型的关系属性更新上的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'})
至于删除,因为您索引了完整的属性映射,我相信您可以用removedRelationshipProperties替换assignedRelationshipPropertiesAssignedRelationshipProperty相当棘手。此参数的结构是Map
其中,第一个字符串是属性的键,列表元素是具有以下键的映射:
键:属性的键
旧值:旧值(如果有)
新建:指定给特性的新值
关系:有问题的关系
为了更直观,以下是调试格式中的参数:
对于您的特定用例,更新特定关系类型的关系属性更新上的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'})
至于删除,因为您对属性的完整映射进行了索引,所以我相信您可以用removedRelationshipProperties替换assignedRelationshipProperties。有专门的帮助函数用于使用这些属性,这些函数在文档中解释用于访问这些数据结构的节点/关系或属性: 见: 表4。辅助函数 函数按标签筛选LabelEntry,以便在具有{assignedLabels}和{removedLabels}的触发器语句中使用 {阶段:'before/after/rollback'} 返回以前的和新的触发器信息
apoc.trigger.propertiesByKey({assignedNodeProperties},'key')
函数按属性键筛选属性项,以便在具有{assignedNode/RelationshipProperties}和{removedNode/RelationshipProperties}的触发器语句中使用
返回[{old、[new]、key、node、relationship}]有专门的帮助函数用于使用这些函数,文档中解释了如何访问这些数据结构的节点/关系或属性: 见: 表4。辅助函数 函数按标签筛选LabelEntry,以便在具有{assignedLabels}和{removedLabels}的触发器语句中使用 {阶段:'before/after r/回滚'} 返回以前的和新的触发器信息
apoc.trigger.propertiesByKey({assignedNodeProperties},'key')
函数按属性键筛选属性项,以便在具有{assignedNode/RelationshipProperties}和{removedNode/RelationshipProperties}的触发器语句中使用
返回[{old,[new],key,node,relationship}]谢谢您的回答。我验证了这个解决方案,但不幸的是它没有work@MichaelHunger抱歉,我忘了提到我已经在更新的问题中对此进行了详细的解释。更新1类似于此问题的章节已在Neo4j 3.4.0/apoc-3.4.0.1-all中修复。谢谢您的回答。我验证了这个解决方案,但不幸的是它没有work@MichaelHunger抱歉,我忘了提到我已经在更新的问题中对此进行了详细的解释。更新1类似于此问题的章节已在Neo4j 3.4.0/apoc-3.4.0.1-all中修复。谢谢您的回答。请参阅我更新的问题更新2。使用这种方法,我也遇到了与前面描述的相同的问题。另一个缺点是,我需要指定确切的密钥名——在本例中是时间。我对某些键感兴趣,但对所有键都不感兴趣。我做错了什么以及如何修复它?顺便说一句。我认为允许该功能过滤标签/rel类型会很好。也许你想为apoc创建一个GH问题。谢谢,我已经为Neo4j创建了一个GH问题。谢谢你的回答。请参阅我更新的问题更新2。使用这种方法,我也遇到了与前面描述的相同的问题。另一个缺点是,我需要指定确切的密钥名——在本例中是时间。但我对某些键不感兴趣,而是对HAS_VALUE_ON关系中所有键的添加/更新/删除感兴趣。我做错了什么以及如何修复它?顺便说一句。我认为允许该函数也可以过滤标签/rel类型也许你想为apoc创建一个GH问题谢谢,我已经为Neo4j创建了一个GH问题:它似乎与更新和索引有关。在查询中,不是触发器。因为常规关系索引有效。@MichaelHunger谢谢!有机会让它工作吗?它似乎与更新和索引有关。在查询中,与触发器无关。因为常规关系索引有效。@MichaelHunger谢谢!有机会让它工作吗?