Neo4j Cypher 查询链表以有条件地创建 NEWEST_REPLY 与将 NEWEST_REPLY 修改为 NEXT_REPLY
Neo4j Cypher query for a linked list to conditionally create a NEWEST_REPLY vs modifying NEWEST_REPLY to NEXT_REPLY
我有一个 Post 的回复链接列表,如下所示:
列表中的“第一个”回复与 Post 具有 NEWEST_REPLY 关系,后续回复具有 NEXT_REPLY 关系。获取上图的查询:
MATCH (p:Post {id: $postId})-[:NEWEST_REPLY|NEXT_REPLY*]->(r:Reply)
return p, r
我想创建一个密码查询
- 创建回复并在没有回复时创建 NEWEST_REPLY 关系或
- 创建回复,删除当前的 NEWEST_REPLY 关系,创建与先前 NEWEST_REPLY 的 NEXT_REPLY 关系和与新回复的 NEWEST_REPLY 关系。
这条语句:
MATCH (p:Post {id: $postId})-[rel:NEWEST_REPLY]->(previousNewestReply:Reply)
DELETE rel
CREATE (r:Reply { id: apoc.create.uuid(), body: $body, createdAt: datetime(), updatedAt: datetime() })
WITH r, p, previousNewestReply
MATCH (u:User)
WHERE u.id = $userId
CREATE (r)<-[:WROTE]-(u)
CREATE (r)<-[:NEWEST_REPLY]-(p)
CREATE (r)-[:NEXT_REPLY]->(previousNewestReply)
RETURN u, p
获得第 2 名。
我现在需要做的是有条件的运行如果MATCH (p:Post {id: $postId})-[rel:NEWEST_REPLY]->(previousNewestReply:Reply)
中的rel
存在,就创建这个语句,如果不存在,就创建NEWEST_REPLY第一次以及创建回复和 User-[:WROTE]->Reply
关系。我是 cypher 的新手,正在深入研究 MERGE、CASE、谓词函数和 apoc.when(),但不确定哪个是最简单和最合适的。
这是使用 CASE 的尝试:
MATCH (p:Post {id: "db7ee38c-fe60-430e-a7c7-0b2514401343"})
RETURN
CASE EXISTS( (p)-[rel:NEWEST_REPLY]->(replies:Reply) )
WHEN true THEN DELETE rel CREATE (r:Reply { id: apoc.create.uuid(), body: "new with CASE1", createdAt: datetime(), updatedAt: datetime() }) WITH r, p, replies MATCH (u:User) WHERE u.id = "e14d409e-d970-4c5c-9cc7-3b224c774835" CREATE (r)<-[:WROTE]-(u) CREATE (r)<-[:NEWEST_REPLY]-(p) CREATE (r)-[:NEXT_REPLY]->(replies)
WHEN false THEN CREATE (r:Reply { id: apoc.create.uuid(), body: "new with CASE2", createdAt: datetime(), updatedAt: datetime() }) WITH r, p, previousNewestReply MATCH (u:User) WHERE u.id = "e14d409e-d970-4c5c-9cc7-3b224c774835" CREATE (r)<-[:WROTE]-(u) CREATE (r)<-[:NEWEST_REPLY]-(p) END
AS result;
与运行宁成如下SyntaxError:
Invalid input 'r': expected whitespace, comment, '{', node labels, MapLiteral, a parameter, a parameter (old syntax), a relationship pattern, '(', '.', '[', '^', '*', '/', '%', '+', '-', "=~", IN, STARTS, ENDS, CONTAINS, IS, '=', '~', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, WHEN, ELSE or END (line 4, column 24 (offset: 145))
"WHEN true THEN DELETE rel CREATE (r:Reply { id: apoc.create.uuid(), body: "new with CASE1", createdAt: datetime(), updatedAt: datetime() }) WITH r, p, replies MATCH (u:User) WHERE u.id = "e14d409e-d970-4c5c-9cc7-3b224c774835" CREATE (r)<-[:WROTE]-(u) CREATE (r)<-[:NEWEST_REPLY]-(p) CREATE (r)-[:NEXT_REPLY]->(replies)"
我的感觉是我在 THEN 语句中尝试的逻辑对于 CASE 来说太复杂了。是否有更合适的方法来从本质上根据特定 Post 是否存在 NEWEST_REPLY 关系来执行 if/else?
您可以执行此操作以删除任何现有的 [:NEWEST_REPLY]
关系:
MATCH (p:Post {id: $postId})
OPTIONAL MATCH (p)-[rel:NEWEST_REPLY]->(previousNewestReply:Reply)
WITH p,previousNewestReply,
// create a collection of size 1 or 0
CASE WHEN NOT rel IS NULL THEN [rel] ELSE [] END AS toBeDeleted
// loop through the collection
FOREACH( tbd IN toBeDeleted | DELETE tbd )
WITH p,previousNewestReply
.....
[更新]
这个查询应该适合你:
MATCH (p:Post), (u:User)
WHERE p.id = $postId AND u.id = $userId
OPTIONAL MATCH (p)-[rel:NEWEST_REPLY]->(prevNewest:Reply)
CREATE (u)-[:WROTE]->(r:Reply {id: apoc.create.uuid(), body: "foo", createdAt: datetime(), updatedAt: datetime()})<-[:NEWEST_REPLY]-(p)
FOREACH(_ IN CASE WHEN rel IS NOT NULL THEN [1] END | DELETE rel CREATE (r)-[:NEXT_REPLY]->(prevNewest))
我假设 postId
和 userId
在 :Post(di)
和 :User(id)
上作为 parameters. Also, you should create indexes 传递以加快查询速度。
我有一个 Post 的回复链接列表,如下所示:
列表中的“第一个”回复与 Post 具有 NEWEST_REPLY 关系,后续回复具有 NEXT_REPLY 关系。获取上图的查询:
MATCH (p:Post {id: $postId})-[:NEWEST_REPLY|NEXT_REPLY*]->(r:Reply)
return p, r
我想创建一个密码查询
- 创建回复并在没有回复时创建 NEWEST_REPLY 关系或
- 创建回复,删除当前的 NEWEST_REPLY 关系,创建与先前 NEWEST_REPLY 的 NEXT_REPLY 关系和与新回复的 NEWEST_REPLY 关系。
这条语句:
MATCH (p:Post {id: $postId})-[rel:NEWEST_REPLY]->(previousNewestReply:Reply)
DELETE rel
CREATE (r:Reply { id: apoc.create.uuid(), body: $body, createdAt: datetime(), updatedAt: datetime() })
WITH r, p, previousNewestReply
MATCH (u:User)
WHERE u.id = $userId
CREATE (r)<-[:WROTE]-(u)
CREATE (r)<-[:NEWEST_REPLY]-(p)
CREATE (r)-[:NEXT_REPLY]->(previousNewestReply)
RETURN u, p
获得第 2 名。
我现在需要做的是有条件的运行如果MATCH (p:Post {id: $postId})-[rel:NEWEST_REPLY]->(previousNewestReply:Reply)
中的rel
存在,就创建这个语句,如果不存在,就创建NEWEST_REPLY第一次以及创建回复和 User-[:WROTE]->Reply
关系。我是 cypher 的新手,正在深入研究 MERGE、CASE、谓词函数和 apoc.when(),但不确定哪个是最简单和最合适的。
这是使用 CASE 的尝试:
MATCH (p:Post {id: "db7ee38c-fe60-430e-a7c7-0b2514401343"})
RETURN
CASE EXISTS( (p)-[rel:NEWEST_REPLY]->(replies:Reply) )
WHEN true THEN DELETE rel CREATE (r:Reply { id: apoc.create.uuid(), body: "new with CASE1", createdAt: datetime(), updatedAt: datetime() }) WITH r, p, replies MATCH (u:User) WHERE u.id = "e14d409e-d970-4c5c-9cc7-3b224c774835" CREATE (r)<-[:WROTE]-(u) CREATE (r)<-[:NEWEST_REPLY]-(p) CREATE (r)-[:NEXT_REPLY]->(replies)
WHEN false THEN CREATE (r:Reply { id: apoc.create.uuid(), body: "new with CASE2", createdAt: datetime(), updatedAt: datetime() }) WITH r, p, previousNewestReply MATCH (u:User) WHERE u.id = "e14d409e-d970-4c5c-9cc7-3b224c774835" CREATE (r)<-[:WROTE]-(u) CREATE (r)<-[:NEWEST_REPLY]-(p) END
AS result;
与运行宁成如下SyntaxError:
Invalid input 'r': expected whitespace, comment, '{', node labels, MapLiteral, a parameter, a parameter (old syntax), a relationship pattern, '(', '.', '[', '^', '*', '/', '%', '+', '-', "=~", IN, STARTS, ENDS, CONTAINS, IS, '=', '~', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, WHEN, ELSE or END (line 4, column 24 (offset: 145))
"WHEN true THEN DELETE rel CREATE (r:Reply { id: apoc.create.uuid(), body: "new with CASE1", createdAt: datetime(), updatedAt: datetime() }) WITH r, p, replies MATCH (u:User) WHERE u.id = "e14d409e-d970-4c5c-9cc7-3b224c774835" CREATE (r)<-[:WROTE]-(u) CREATE (r)<-[:NEWEST_REPLY]-(p) CREATE (r)-[:NEXT_REPLY]->(replies)"
我的感觉是我在 THEN 语句中尝试的逻辑对于 CASE 来说太复杂了。是否有更合适的方法来从本质上根据特定 Post 是否存在 NEWEST_REPLY 关系来执行 if/else?
您可以执行此操作以删除任何现有的 [:NEWEST_REPLY]
关系:
MATCH (p:Post {id: $postId})
OPTIONAL MATCH (p)-[rel:NEWEST_REPLY]->(previousNewestReply:Reply)
WITH p,previousNewestReply,
// create a collection of size 1 or 0
CASE WHEN NOT rel IS NULL THEN [rel] ELSE [] END AS toBeDeleted
// loop through the collection
FOREACH( tbd IN toBeDeleted | DELETE tbd )
WITH p,previousNewestReply
.....
[更新]
这个查询应该适合你:
MATCH (p:Post), (u:User)
WHERE p.id = $postId AND u.id = $userId
OPTIONAL MATCH (p)-[rel:NEWEST_REPLY]->(prevNewest:Reply)
CREATE (u)-[:WROTE]->(r:Reply {id: apoc.create.uuid(), body: "foo", createdAt: datetime(), updatedAt: datetime()})<-[:NEWEST_REPLY]-(p)
FOREACH(_ IN CASE WHEN rel IS NOT NULL THEN [1] END | DELETE rel CREATE (r)-[:NEXT_REPLY]->(prevNewest))
我假设 postId
和 userId
在 :Post(di)
和 :User(id)
上作为 parameters. Also, you should create indexes 传递以加快查询速度。