Neo4j APOC分配的RelationshipProperties、removedRelationshipProperties触发器和APOC.index.in

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

我使用带有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 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替换assignedRelationshipProperties

AssignedRelationshipProperty相当棘手。此参数的结构是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谢谢!有机会让它工作吗?