如果存在端节点,则创建节点和关系(否则仅创建第一个节点)

时间:2017-02-08 17:18:58

标签: node.js neo4j cypher

我有一个应用程序通过消息队列向工作人员发送数据库写入命令(非常高的数量),因此不能保证他们将收到它们的顺序。

我有两个节点,例如“帐户”和“媒体”。在这个假设的应用程序中,用户可以上传匿名媒体,这会自动为他们创建一个帐户,然后他们可以在以后关联。

将收到两条消息,一条用于帐户,一条用于媒体(几乎可以肯定是由不同的工作人员)。他们都不知道对方是否已经写好了。我需要编写一个将在每个worker上运行的查询,其中包括:

  • 创建新帐户/媒体
  • 如果存在其他节点,请在两个
  • 之间创建POSTED_BY关系
  • 如果其他节点不存在,则仅创建当前节点
  • 返回新创建的节点

因此,无论接收每条消息的顺序如何,第一个查询将创建节点A,第二个查询将创建节点B +关系。

如果我在同一个查询中创建它们,那很简单:

CREATE (m:Media { url: 'xyz.jpg' })-[:POSTED_BY]->(u:Account { username: 'johndoe' })
RETURN m,u

我查看了CREATE UNIQUEMERGE,但是如果它不存在,它们似乎都会创建节点,而不是什么都不做。

2 个答案:

答案 0 :(得分:1)

我认为您希望使用MERGE进行此操作。实质上,您可以创建节点和关系,而不是一次创建一个节点,而是使用其他属性更新特定节点。

考虑 Message One 是媒体消息

MERGE (m:Media { url: 'xyz.jpg' })
SET m =+ {media_props}
MERGE (u:Account { username: 'johndoe' })
MERGE (m)-[:POSTED_BY]->(u)
RETURN m

考虑消息二是新用户帐户消息

MERGE (u:Account { username: 'johndoe' })
SET u =+ {user_props}
MERGE (m:Media { url: 'xyz.jpg' })
MERGE (m)-[:POSTED_BY]->(u)
RETURN u

您可以想象通过MERGE单独创建每个节点,并为该关系提供第三条消息。模式将是相同的,但不会在任一节点上设置任何其他属性。

例如......

// message 1
// create the media node
MERGE (m:Media { url: 'xyz.jpg' })
SET m =+ {media_props}
RETURN m


// message 2
// create the user/account node
MERGE (u:Account { username: 'johndoe' })
SET u =+ {user_props}

// message 3
// create the relationship
MERGE (u:Account { username: 'johndoe' })
MERGE (m:Media { url: 'xyz.jpg' })
MERGE (m)-[r:POSTED_BY]->(u)
RETURN m,r,u

请注意,所有解决方案都假定用于标识合并声明中的媒体和帐户的密钥是唯一的。

答案 1 :(得分:0)

我知道答案已被接受,但不要觉得它实际上回答了这个问题,即:

  

如果另一个节点不存在,则只创建当前节点

这可以通过以下方式实现:

CREATE (m:Media { url: 'xyz.jpg' })
WITH m 
MATCH(u:Account { username: 'johndoe' }) 
CREATE(m)-[r:POSTED_BY]->(u)"
RETURN m

不幸的是,如果匹配成功,这只会返回m