neo4j 用于查找或创建关系并将其count属性加一查询

siv3szwd  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(188)

我想计算“一个节点连接到另一个节点的次数”。
在两个相同的节点之间有多个冗余关系似乎不是一个好主意,因此我认为应该使用一个带有“count”属性的关系来实现这个目的。
但是如何更新这些关系并增加属性“计数”呢?
Neo4j没有任何属性的自动递增功能(根据我所读到的)。
作为一种替代方法,我想在Python中MATCH现有的关系(如果它存在的话),然后更新它的count属性,但是似乎没有任何效果。
以下是我目前所掌握的情况:

def create_or_increment_relationship(tx, start_node_label, start_node_property, new_node_label, new_node_property, relationship_type):

    return tx.run(

        "MATCH (s) WHERE (s.label = $start_node_label AND s.name = $start_node_property) \n \
        CALL apoc.merge.node($new_node_label, {name: $new_node_property}) \n \
        MATCH (s)-[r:$relationship_type]->(n) \n \
        CALL apoc.merge.relationship(s, $relationship_type, r.count+1, n);",

        start_node_label=start_node_label,
        start_node_property=start_node_property,
        new_node_label=new_node_label,
        new_node_property=new_node_property,
        relationship_type=relationship_type,

    ).single().value()

上面的查询(绿色)有4行:

  • 查找start_node(s,应该已经存在)
  • 查找或创建new_node(n,有时不存在)
  • 求出它们之间的关系(r,如果n不存在,r就不存在)
  • 如果存在,则将其“count”属性加1,否则将其设置为1(r.count)

我知道我还需要使用APOC来匹配一个基于运行时建立的标签(动态标签,即Python变量)的现有关系(这是本代码查询部分的第三行)。
然而,我找不到任何这样的查询的例子,或者一个apoc函数,它匹配的条件关系。
UPDATE:显然,APOC中匹配关系的一种方法是使用apoc.merge.relationship,如本文所述https://github.com/neo4j-contrib/neo4j-apoc-procedures/issues/2674
在第二个例子中,我使用apoc.merge.node来匹配起始节点和结束节点,而没有实际创建或更改它们。我的假设是,Neo4j仍然会对这些节点进行写锁定,这会影响性能,并会由于同一节点上的死锁而阻碍优化,例如通过apoc.periodic.iterate进行并行化。
......致APOC的维护者:我同意如果有apoc.match.relationship(或node)函数就更好了。我认为这是为了API的易用性/理解性/清晰性;这张海报还说,在某些情况下,专用的实现可以带来性能优势。

llycmphe

llycmphe1#

需要考虑的事项:
1.下面的语句在使用参数化查询时不起作用。因此,您的查询在此语句之后不返回数据。因此,在最后一行中不会创建任何关系
匹配(s)-[r:$关系类型]-〉(n)
修复:当变量是关系类型时,需要使用python进行字符串替换。
1.如果前一个MATCH语句没有返回行,则不会创建一个关系。查询将直接结束,而不运行最后一个apoc语句。
修复:在MATCH的CREATE上使用MERGE
1.此外,在您的查询中有打字错误,所以我建议您通过复制您生成的实际语句来调试密码查询,然后在neo4j控制台中运行它。
修复:查看查询的第1行和第2行。
下面是您可以使用的代码片段。

from neo4j import GraphDatabase 

uri="bolt://localhost:7687"
user="neo4j"
password="<awesome_psw>"

driver = GraphDatabase.driver(uri, auth=(user, password))
session = driver.session()

start_node_label = 'Person'
start_node_property = 'user' 
new_node_label = 'NewPerson'
new_node_property = 'newuser'
relationship_type = 'RELATED_TO'

cypher = "MATCH (s) WHERE $start_node_label in labels(s) AND s.name = $start_node_property \n \
          CALL apoc.merge.node([$new_node_label], {{name: $new_node_property}}) YIELD node as n \n \
          MERGE (s)-[r:{relationship_type}]->(n) \n \
             ON CREATE set r.count = 1  \n \
             ON MATCH set r.count = r.count + 1 \n \
          RETURN r;"
query  = cypher.format(relationship_type = relationship_type)
result = session.run(query,
        start_node_label=start_node_label,
        start_node_property=start_node_property,
        new_node_label=new_node_label,
        new_node_property=new_node_property,
        relationship_type=relationship_type)
d = result.single().value() 
print(d)

样本结果:

<Relationship id=7 nodes=(<Node id=8 labels=frozenset() properties={}>, <Node id=7 labels=frozenset() properties={}>) type='HAS' properties={'count': 1}>

相关问题