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
我最终将其分成两个查询。
我发现的问题是我注意到有两种可能的结果。
已创建 CREATED_BY
关系并使用 OPTIONAL MATCH
返回 (n)
,如果 [=] 之间不存在此关系,则始终会创建该关系15=] 和 (u)
,因此当更改电子邮件属性时,它将重新创建关系。
找不到节点 (n)
(因为没有使用 OPTIONAL MATCH
和 WHERE 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
节点。
我想在我的数据库中的节点上添加一个 "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
我最终将其分成两个查询。
我发现的问题是我注意到有两种可能的结果。
已创建
CREATED_BY
关系并使用OPTIONAL MATCH
返回(n)
,如果 [=] 之间不存在此关系,则始终会创建该关系15=] 和(u)
,因此当更改电子邮件属性时,它将重新创建关系。找不到节点
(n)
(因为没有使用OPTIONAL MATCH
和WHERE 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
节点。