我有一个事件的节点ID,以及托管该事件的用户的节点ID列表。我想更新这些(:USER) - [:HOSTS] - >(:EVENT)关系。我不想添加新的,我也想删除旧的。
注意:这是coffeescript语法,其中#{}是字符串插值,str()将为我转义任何字符。
现在我正在查询所有主持人:
MATCH (u:USER)-[:HOSTS]->(:EVENT {id:#{str(eventId)}})
RETURN u.id
然后我决定哪些主机是新主机,需要添加哪些主机,哪些主机是旧的,需要删除。对于旧的,我删除它们
MATCH (:HOST {id:#{str(host.id)}})-[h:HOSTS]->(:EVENT {id:#{str(eventId)}})
DELETE h
对于新的,我添加它们:
MATCH (e:EVENT {id: #{str(eventId)}})
MERGE (u:USER {id:#{str(id)}})
SET u.name =#{str(name)}
MERGE (u)-[:HOSTS]->(e)
所以我的问题是,我可以在一个查询中更有效地执行此操作吗?我想要设置新的关系,摆脱以前在新集合中不存在的关系。
答案 0 :(得分:2)
如果我正确理解您的问题,您可以通过引入WITH
和FOREACH
在单个查询中实现您的目标。在由
CREATE (_1:User { name:"Peter" }),(_2:User { name:"Paul" }),(_3:User { name:"Mary" })
CREATE (_4:Event { name:"End of the world" })
CREATE _1-[:HOSTS]->_4, _2-[:HOSTS]->_4
您可以删除不再相关的主机,并添加新主机
WITH ["Peter", "Mary"] AS hosts, "End of the world" AS eventId
MATCH (event:Event { name:eventId })<-[r:HOSTS]-(u:User)
WHERE NOT u.name IN hosts
DELETE r
WITH COLLECT(u.name) AS oldHosts, hosts, event
WITH FILTER(h IN hosts
WHERE NOT h IN oldHosts) AS newHosts, event, oldHosts
FOREACH (n IN newHosts |
MERGE (nh:User { name:n })
MERGE nh-[:HOSTS]->event
)
我做了一些假设,至少包括
:User
)可能已经存在,因此MERGE (nh:User { name:n })
而不是CREATE
。[:HOSTS]
应与事件断开连接,但不会从数据库中删除。单击here以测试查询。将hosts
数组的内容更改为["Peter", "Paul"]
,或更改为["Peter", "Dragon"]
或任何对您有意义的值,然后重新运行查询以查看其工作原理。我已经使用name
而非id
来捕获节点,而且我已经模拟了参数,但您可以将查询转换为您想要的上下文执行它。
修改强>
重新评论,如果您希望查询也匹配不具有任何主机的事件,则需要使模式的-[:HOSTS]-
部分成为可选项。通过将MATCH
子句制动为两个来实现:
MATCH (event:Event { name:eventId })
OPTIONAL MATCH event<-[r:HOSTS]-(u:User)
查询的其余部分是相同的。