【问题标题】:Neo4j APOC assignedRelationshipProperties, removedRelationshipProperties triggers and apoc.index.inNeo4j APOC 分配了RelationshipProperties,removedRelationshipProperties 触发器和apoc.index.in
【发布时间】:2018-05-09 12:59:45
【问题描述】:

我使用Neo4j 3.3.5 Community EditionAPOC apoc-3.3.0.2-all.jar

我有触发器允许我在手动索引中添加/删除特定关系中的所有属性:

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) 关系的索引中的属性?

更新 #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

查询返回空结果,目前还可以。

分配关系新属性time,值=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

查询成功返回预期的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

查询对他们两个都返回空结果..

为什么属性更改后索引没有更新?

更新 #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

查询返回空结果,目前还可以。

分配关系新属性time,值=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

查询成功返回预期的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

查询对他们两个都返回空结果..

因此,这种方法遇到了与我之前描述的相同的问题。另一个缺点是我需要指定确切的键名——在本例中为time。但我对某些特定键不感兴趣,而是对 HAS_VALUE_ON 关系的所有键的添加/更新/删除感兴趣。

【问题讨论】:

  • 它似乎与更新和index.in 查询有关,而不是触发器。作为常规关系索引的工作原理。
  • @MichaelHunger 谢谢!有机会让它工作吗?

标签: neo4j cypher neo4j-apoc


【解决方案1】:

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

【讨论】:

  • 感谢您的回答。我验证了这个解决方案,但不幸的是它不起作用
  • @MichaelHunger 抱歉,我忘了提到我已经在我更新的问题中提供了对此的详细解释(此方法不适用于什么) - 更新 #1 部分
  • 看起来这个问题已在 Neo4j 3.4.0/apoc-3.4.0.1-all.jar 中得到修复
【解决方案2】:

有专门的辅助函数来使用这些,文档中解释了这些函数来访问节点/rels 或这些数据结构的属性:

见:https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_triggers

表 4. 辅助函数

apoc.trigger.nodesByLabel({assignedLabels/assignedNodeProperties},'Label')

按标签过滤标签条目的函数,用于{assignedLabels}{removedLabels}的触发器语句 {phase:'before/after/rollback'} 返回上一个和新的触发信息

apoc.trigger.propertiesByKey({assignedNodeProperties},'key')

按属性键过滤属性条目的函数,用于{assignedNode/RelationshipProperties}{removedNode/RelationshipProperties} 的触发器语句中。

返回[{old,[new],key,node,relationship}]

【讨论】:

  • 感谢您的回答。请参阅我更新的问题(更新#2)。使用这种方法,我也遇到了与前面描述的相同的问题。另一个缺点是我需要指定确切的键名——在本例中为time。但我对某些特定键不感兴趣,而是对 HAS_VALUE_ON 关系的所有键的添加/更新/删除感兴趣。我做错了什么以及如何解决?
  • 顺便说一句。我认为还允许该函数过滤标签/rel 类型会很好,也许您想为此创建一个 apoc 的 GH 问题
  • Neo4j 的另一个 GH 问题:github.com/neo4j/neo4j/issues/11789
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
相关资源
最近更新 更多