我一直在试图找到一种方法来使py2neo v2中的merge_one功能适应v3。我在Google group中读到“在v3中不再存在merge_one方法,因为您应该能够在所有情况下使用合并。”但我无法弄清楚如何在v3中轻松使用常规合并。
我正在尝试通过一些小修改来重新创建Nicole White's neo4j twitter example项目。她使用了merge_one。对(u:User) - u.username和(t:Tweet) - t.id有唯一性约束。她的脚本总是具有Tweet和User节点的相同属性,但我提出了一个案例,有时我想回去并通过合并向现有节点添加更多属性。但是我收到了错误
py2neo.database.status.ConstraintError: Node 178 already exists with label Tweet and property "id"=[***]
我理解这是因为当我有一个已经存在且只有一个id而且我尝试做的推文时
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)
merge并没有找到与所有这些属性相同的推文,并且当它试图创建一个正在运行到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进行合并,然后设置匹配或设置为create但我不知道如何使用py2neo。我还试图在文档中找到允许从具有现有节点的字典中更新属性但不能更新的内容。
答案 0 :(得分:7)
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 :(得分:7)
两件事;
1)。 tweet.push()已被弃用。文档建议使用graph.push(tweet)。
2)。 我无法通过以下事务处理此问题:
transaction = graph.begin()
transaction.merge(tweet)
transaction.graph.push(tweet)
transaction.commit()
有关使用graph.merge
和transaction.merge
答案 2 :(得分: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)