避免为每个匹配创建多个关系

时间:2020-05-22 18:16:16

标签: neo4j cypher

我有以下模型,每个User通过Comment关系链接到几个AUTHORED节点,每个注释都有一个flair属性,每个属性可以不同评论。我也有一个Flair节点,并希望在User节点和Flair节点之间创建新的关系。

+--------+                          +---------+
|        |                          |         |
|  User  +------+ REL:AUTHORED+-----+ Comment |
|        |                          |         |
+--------+                          +---------+

因此,我编写了以下查询来尝试执行此操作,但是对于每个User节点,Comment节点都具有正确的风格。我只想要这些节点之间的单一关系。我该如何实现?

MATCH (a:User)-[:AUTHORED]-(c:Comment),(b:Flair)
WHERE c.flair = 'foo' and b.name = 'foo'
CREATE (a)-[r:VOTES_FOR]->(b)
RETURN type(a,b,r)

2 个答案:

答案 0 :(得分:1)

为避免创建重复关系,应使用MERGE而不是CREATE

MATCH (a:User)-[:AUTHORED]->(c:Comment), (b:Flair)
WHERE c.flair = 'foo' AND b.name = 'foo'
MERGE (a)-[r:VOTES_FOR]->(b)
RETURN a, b, r

此查询还删除了TYPE函数的使用,因为您的查询非法使用了该函数。

但是我还应该注意,您正在通过添加VOTES_FOR关系将冗余数据引入数据库。相反,我建议从flair节点中删除Comment属性,并用CommentFlair节点之间的关系替换它。下面的查询应该可以达到目的(并且还可以避免将相同的信息冗余地存储在多个位置)。此外,它还处理所有风格的值(不仅仅是“ foo”):

MATCH (u:User)-[:AUTHORED]->(c:Comment), (f:Flair)
WHERE c.flair = f.name
REMOVE c.flair
MERGE (c)-[:FOR_FLAIR]->(f)
RETURN u, c, f

或者,更有效地,如果您真的不需要返回User

MATCH (c:Comment), (f:Flair)
WHERE c.flair = f.name
REMOVE c.flair
MERGE (c)-[:FOR_FLAIR]->(f)
RETURN c, f

有了这个新的数据模型,您可以找到用户以这种方式创作的所有独特的Flair:

MATCH (user:User)-[:AUTHORED]->()-[:FOR_FLAIR]->(flair)
WHERE user.id = 123
RETURN user, COLLECT(DISTINCT flair) AS flairs

答案 1 :(得分:0)

您想使用MERGE而不是CREATE来使这些节点之间只有一个关系。

MATCH (a:User)-[:AUTHORED]-(c:Comment),(b:Flair)
WHERE c.flair = 'foo' and b.name = 'foo'
MERGE (a)-[r:VOTES_FOR]->(b)
RETURN type(a,b,r)