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

我想创建一个密码查询

  1. 创建回复并在没有回复时创建 NEWEST_REPLY 关系或
  2. 创建回复,删除当前的 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))

我假设 postIduserId:Post(di):User(id) 上作为 parameters. Also, you should create indexes 传递以加快查询速度。