Cypher,为一个节点创建唯一关系

Cypher, create unique relationship for one node

我想在我的数据库中的节点上添加一个 "created by" 关系。任何节点都应该能够拥有这种关系,但永远不能超过一个。

现在我的查询看起来像这样:

MATCH (u:User {email: 'my@mail.com'})
MERGE (n:Node {name: 'Node name'})
ON CREATE SET n.name='Node name', n.attribute='value'
CREATE UNIQUE (n)-[:CREATED_BY {date: '2015-02-23'}]->(u)
RETURN n

据我所知,Cypher 无法实现我想要的,当前查询只会确保没有基于两个节点(而不是一个)的唯一关系。因此,当另一个用户 运行 时,这将创建更多 CREATED_BY 关系,我想将传出 CREATED_BY 关系限制为所有节点仅一个。

有没有办法在不 运行涉及程序逻辑的多个查询的情况下实现这一点?

谢谢。

更新

我试图通过删除实现细节来简化查询,如果它有帮助,这里是基于 cybersams 响应的更新查询。

MERGE (c:Company {name: 'Test Company'}) 
ON CREATE SET c.uuid='db764628-5695-40ee-92a7-6b750854ebfa', c.created_at='2015-02-23 23:08:15', c.updated_at='2015-02-23 23:08:15' 
WITH c
OPTIONAL MATCH (c)
WHERE NOT (c)-[:CREATED_BY]-() 
CREATE (c)-[:CREATED_BY {date: '2015-02-23 23:08:15'}]->(u:User {token: '32ba9d2a2367131cecc53c310cfcdd62413bf18e8048c496ea69257822c0ee53'})  
RETURN c

仍然没有按预期工作。

更新 #2

我最终将其分成两个查询。

我发现的问题是我注意到有两种可能的结果。

  1. 已创建 CREATED_BY 关系并使用 OPTIONAL MATCH 返回 (n),如果 [=] 之间不存在此关系,则始终会创建该关系15=] 和 (u),因此当更改电子邮件属性时,它将重新创建关系。

  2. 找不到节点 (n)(因为没有使用 OPTIONAL MATCHWHERE NOT (c)-[:CREATED_BY]-() 子句),导致没有创建关系(耶!)但是没有得到 (n) 返回 MERGE 查询失去了我认为的所有含义。

我的解决方案是以下两个查询:

MERGE (n:Node {name: 'Name'})
ON CREATE SET
SET n.attribute='value'
WITH n
OPTIONAL MATCH (n)-[r:CREATED_BY]-()
RETURN c, r

然后我让程序逻辑检查 r 的值,如果没有关系我会 运行 第二个查询。

MATCH (n:Node {name: 'Name'})
MATCH (u:User {email: 'my@email.com'})
CREATE UNIQUE (n)-[:CREATED_BY {date: '2015-02-23'}]->(u)
RETURN n

不幸的是,我找不到任何真正的解决方案来将它与 Cypher 结合在一个查询中。山姆,谢谢!我选择了你的答案,尽管它并没有完全解决我的问题,但已经非常接近了。

这应该适合你:

MERGE (n:Node {name: 'Node name'})
ON CREATE SET n.attribute='value'
WITH n
OPTIONAL MATCH (n)
WHERE NOT (n)-[:CREATED_BY]->()
CREATE UNIQUE (n)-[:CREATED_BY {date: '2015-02-23'}]->(:User {email: 'my@mail.com'})
RETURN n;

我删除了开始的 MATCH 子句(因为我假设您想要创建一个 CREATED_BY 关系,即使 User 在数据库中尚不存在),并且简化了 ON CREATE 以删除 name 属性.

的冗余设置

我还添加了一个 OPTIONAL MATCH,它将只匹配一个 n 节点,该节点还没有传出 CREATED_BY 关系,后跟一个 CREATE UNIQUE 子句完全指定 User 节点。