在Neo4j中创建节点时如何跳过重复的节点

时间:2018-11-09 01:10:45

标签: javascript node.js neo4j cypher

我有一个用于创建节点的电子邮件地址列表。但是,如果这些电子邮件地址之一已经存在,则我不想收到CATCH'....节点已存在'错误,因为这将杀死整个查询,并且不会创建任何节点。因此,在创建节点之前,我先使用MERGE然后ON CREATE检查电子邮件地址是否存在。问题是我需要与第二个节点创建关系,因此在MERGE和ON CREATE之后,我必须使用WITH .... CREATE来创建关系,这就是问题所在... WITH不在'scope范围内'的ON CREATE,因此CREATE(a)-[r]->(b)现在尝试使用我在上面的MERGE中跳过的电子邮件地址创建一个节点...导致CATCH'...已经存在...”错误地将我的查询删除。这是我的CYPHER:

 commons.session
      .run['tom@abc.com', 'tony@mymail.com',michael@gmail.com'] AS coll
        UNWIND coll AS invitee
        WITH DISTINCT invitee
        MERGE (i {email: invitee})
        ON CREATE
          SET i:Invitee
        WITH i,invitee
        CREATE (s:Person {email: 'xyz123@abc.com})-[r:INVITED]->(i)
        RETURN i.email AS emails, COUNT(r) AS invitees)

我希望返回的是仅创建了节点和关系的电子邮件地址的列表。基本上,我需要处于ON CREATE的“作用域”中,因为重复项将被跳过。对此工作的任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

[更新2]

WITH [
  {email:'tom@abc.com', name:'tom'},
  {email:'tony@mymail.com', name:'tony'},
  {email:'michael@gmail.com', name:'mike'}] AS coll
MATCH (s:Person {email: 'me@aol.com'})
OPTIONAL MATCH (s)-[x:INVITED]->()
WITH s, coll, COUNT(x) AS orig_count
UNWIND coll AS invitee
WITH DISTINCT s, orig_count, invitee
OPTIONAL MATCH (i {email: invitee.email, name: invitee.name})
FOREACH(ignored IN CASE WHEN i IS NULL THEN [1] ELSE [] END |
  CREATE (s)-[r:INVITED]->(:Invitee {email: invitee.email, name: invitee.name})
)
WITH s, orig_count
OPTIONAL MATCH (s)-[x:INVITED]->()
RETURN COUNT(DISTINCT x) - orig_count AS new_relationship_count

说明:

  • 如果找不到节点模式,则OPTIONAL MATCH子句将为NULL生成一个i值。
  • CASE WHEN i IS NULL THEN [1] ELSE [] END将仅当iNULL时返回非空列表。
  • 如果列表为空,则FOREACH子句将不会执行其包含的write子句。否则,它将执行所有这些命令。
  • 首先,此查询首先获得从orig_count传出的INVITED个关系的原始数量的计数(s
  • 最后,它得到一个最终计数并从中减去orig_count以获得new_relationship_count

答案 1 :(得分:0)

好吧...所以FOREACH和CASE都没有成功。实际上,WHERE子句可以。如问题中所述,我最初的需求是接受电子邮件列表,创建列表中不存在用于电子邮件的节点的节点,并返回已创建电子邮件节点的列表以及数量...。并且没有在“电子邮件已存在...”错误CATCH语句上失败。这是我提出的解决方案:

<IfModule reqtimeout_module>
      RequestReadTimeout header=0
      RequestReadTimeout body=0
</IfModule>

使用WHERE子句,我可以只关注那些尚未创建节点的电子邮件。

感谢@cybersam对OPTIONAL MATCH的建议以及为可能的解决方案而进行的迭代。