当节点已存在时,在NEO4J中使用UNWIND创建多个节点

时间:2018-06-04 00:19:47

标签: neo4j cypher

我正在使用UNWIND在NEO4j中创建多个节点。问题是如果其中一个节点是重复节点,它将被拒绝并且整个查询失败。我希望能够在相同节点之间创建多个关系(如果它们已经存在)。例如,朋友可以从同一个人那里收到多个邀请。所以我有一系列对象[{email:xxx@mail.com},{email:yyy@mymail.com},...]被邀请,以及赞助商赞助商电子邮件的电子邮件。电子邮件存在约束,因此尝试创建重复项将失败并拒绝整个查询。如果没有重复,以下工作正常。

MATCH (s {email: 'sponsor@gmail.com'})
UNWIND $arrayOfObjects as invitees
CREATE (i:Invitee) MERGE (s)-[r:INVITED {since: timestamp()}]->(i)
SET i=invitees

我已经尝试用MERGE替换CREATE,认为MERGE会找到一个MATCH并继续创建关系,但它不起作用..我仍然会得到重复的错误。如果没有在执行查询之前清理arrayOfObjects,还有另一种方法吗?我想要的是复制不会失败,而是与现有的Invitee节点建立关系。

3 个答案:

答案 0 :(得分:1)

您需要合并:Invitee节点以及被邀请者电子邮件。就像现在一样,您正在创建空的:Invitee节点,并且只有在创建它们之后才设置电子邮件地址。您需要使用电子邮件地址将它们与合并。 (你也应该在你的第一个MATCH上使用一个标签,否则它会使用AllNodesScan ......我现在假设它是:邀请者,但请用任何标签来替换。)

MATCH (s:Invitee {email: 'sponsor@gmail.com'})
UNWIND $arrayOfObjects as invitee
MERGE (i:Invitee {email:invitee.email}) 
CREATE (s)-[r:INVITED {since: timestamp()}]->(i)

答案 1 :(得分:1)

[EDITED]

您的MERGE可以匹配任何现有Invitee,并且您的SET可能会尝试将其email值更改为非唯一值。这可能是您违反约束的原因。

如果您只想为每个被邀请者提供一个INVITED关系(带有最新时间戳),则此查询可能会执行您想要的操作:

MATCH (s {email: 'sponsor@gmail.com'})
UNWIND $arrayOfObjects as invitee
MERGE (i:Invitee {email: invitee.email})
ON CREATE SET i = invitee
MERGE (s)-[r:INVITED]->(i)
ON CREATE SET r.since = timestamp()

此查询假定arrayOfObjects中的每个地图都包含唯一的email属性值。 (您还应该在:Invitee(email)上创建indexuniqueness constraint以加快第一个MERGE。)

MERGE (s)-[r:INVITED {since: timestamp()}]->(i)子句(指定当前时间戳)存在缺陷,因为它不会检测到具有较旧since值的现有关系 - 因此它几乎总是会创建新关系。 MERGE (s)-[r:INVITED]->(i)子句只会在不存在的情况下创建关系。

或者,如果要跟踪每个邀请的时间戳,可以将since值设为时间戳数组,如下所示:

MATCH (s {email: 'sponsor@gmail.com'})
UNWIND $arrayOfObjects as invitee
MERGE (i:Invitee {email: invitee.email})
ON CREATE SET i = invitee
MERGE (s)-[r:INVITED]->(i)
ON CREATE SET r.since = [timestamp()]
ON MATCH SET r.since = r.since + timestamp()

答案 2 :(得分:0)

提交的答案都是很好的答案。对于那些以后来的人,我提出这个答案有一些细微差别。该问题的主要目的是能够为尚未接受并能够可视化这些邀请的朋友创建多个邀请。以下是我的决定:

WITH ['tom@abc.com', 'tony@mymail.com',michael@gmail.com'] AS coll
UNWIND coll AS invitee
WITH DISTINCT invitee
MATCH (s:Sponsor {email: 'mary@gmail.com'})
MERGE (i:Invitee {email: invitee})
CREATE (s)-[r:INVITED {since: timestamp()}]->(i)
RETURN r;   

这允许我为发送给同一个人的每个邀请创建多个关系,但仅限于在不同时间发送....我可以轻松查看。