py2neo - 使用唯一性约束 (merge_one) 更新已存在的节点与新属性

7
我一直在尝试将py2neo v2中的merge_one功能适应到v3中。我在Google group中读到“在v3中,merge_one方法不再存在,因为你应该能够在所有情况下都使用merge。”但我无法弄清楚如何在v3中轻松地使用常规合并。
我正在尝试使用一个小修改来重新创建Nicole White的neo4j twitter示例项目。她使用了merge_one。在(u:User)- u.username和(t:Tweet)- t.id上有唯一性约束。她的脚本始终具有Tweet和User节点的相同属性,但我正在创建一个情况,有时我想返回并使用merge添加更多属性到现有节点。然而,我收到以下错误: py2neo.database.status.ConstraintError: Node 178 already exists with label Tweet and property "id"=[***] 我理解这是因为当我有一个只有id的Tweet已经存在时,然后我尝试做
        tw_dict = {'id'=t['id'], 'text':t['text'], 'created':t['created_at'],
               'rts':t['retweet_count'],
               'favs':t['favorite_count'], 'lang':t['lang']}
        tweet = Node("Tweet", **tw_dict)
        graph.create(tweet)

合并操作无法找到所有具有相同属性的推文,当它尝试创建一个时,会遇到Tweet ID唯一性约束的问题。看起来merge_one函数可以解决这个问题,但在v3中不可用。因此,我实现了以下解决方案:

    exists = graph.find_one("Tweet", "id", t['id'])
    if exists:
        exists['text'] = t['text']
        exists['created'] = t['created_at']
        exists['rts'] = t['retweet_count']
        exists['favs'] = t['favorite_count']
        exists['lang'] = t['lang']
    else:
        tw_dict = {'text':t['text'], 'created':t['created_at'],
               'rts':t['retweet_count'],
               'favs':t['favorite_count'], 'lang':t['lang']}
        tweet = Node("Tweet", **tw_dict)
        graph.create(tweet)

但这对我来说似乎很重复。在py2neo中是否没有更简单的方法来更新具有唯一约束条件(在这种情况下是id)的节点并仍指定属性?我认为在Cypher中,我会对仅id进行合并,然后根据匹配设置或创建进行设置,但我不知道如何在py2neo中实现。我也尝试在文档中找到允许使用现有节点的字典更新属性的内容,但没有找到。

3个回答

10

两个问题:

1.) tweet.push() 已被弃用。文档建议使用 graph.push(tweet)。

2.) 我在使用事务时遇到了麻烦,例如:

transaction = graph.begin()
transaction.merge(tweet)
transaction.graph.push(tweet)
transaction.commit()

有什么建议可以解释一下使用graph.mergetransaction.merge的区别吗?

不是真正的答案,但我只能让它起作用,将push方法的调用移出事务... - Stefano Bragaglia

9

py2neo v3现在有了graph.merge(),您可以使用它来达到相同的效果。

首先使用graph.merge()查找或创建节点,仅匹配其唯一属性,然后使用node.push()更新其其他非唯一属性。您将需要使用graph.merge_one()做同样的事情,只是语法略有不同。

from py2neo import Graph, Node
graph = Graph()

tweet = Node('Tweet', id=123)
graph.merge(tweet)
tweet['text'] = 'Hello World'
tweet.push()

我应该更新那个Twitter脚本,使用py2neo v3;感谢提醒。


1
谢谢,我没想到你可以像那样在合并节点时通过推送更改节点的属性。顺便说一下,你的例子对于学习如何使用neo4j和Python处理Twitter数据非常有帮助! - Neil Aronson
谢谢!另外,我已经更新了你在问题中提供的脚本,使用了py2neo v3。 - Nicole White
将节点推送(即[node].push)会导致运行时错误。我需要使用graph.push(node)来代替。 - Ilan
我收到一个错误,节点对象没有属性“push”。 - user11862294
使用 graph.push(tweet)。 - Erangad

0

针对 py2neo v5 - 2020 的更新,您可以从字典中更新现有节点的多个属性。

from py2neo import NodeMatcher
tw_dict = {'text':t['text'], 
           'created':t['created_at'],
           'rts':t['retweet_count'],
           'favs':t['favorite_count'], 
           'lang':t['lang']}
tweet = matcher.match('Tweet', id=123).first()
if tweet:
    tweet.update(**properties)
    graph.push(tweet)

我认为你的意思是 tweet.update(**tw_dict)。 - badr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接