密码查询,用于将节点从一种列表结构移动到另一种列表结构 [英] Cypher query for moving nodes from one list structure to another
问题描述
我们具有以下结构,其中用户是起点,编号为节点的节点标记为邀请,其值指定了其属性 id 。
We have following structure where User is starting point and nodes with numbers are labeled Invitation where its value specify their property id.
我正在寻找一种创建查询的方法它将节点从VALID_INVITATIONS关系指向的列表移到INVALID_INVITATIONS指向的另一个列表。应该在新列表中首先设置移动的节点。
I am looking for a way to create a query which moves node from list pointed by VALID_INVITATIONS relationship to another list pointed by INVALID_INVITATIONS. Moved node should be set first in new list.
我想出了一个可行的解决方案,但是由于缺乏Cypher的知识和经验,请向社区寻求帮助。及其改进。
正如您将看到的,有很多命令式代码 hacks(CASE WHEN),而不是Cypher应该是声明式的。对于所有的提示和建议,我将不胜感激
I came up with working solution but because of lack of knowledge and experience in Cypher I kindly ask you, the community for help and improvements for it. As you will see there is a lot of imperative code "hacks" (CASE WHEN) instead of declarative as Cypher supposed to be. I would appreciate for all hints and advices
MATCH (u:User)
MATCH (u)-[:VALID_INVITATIONS|PREVIOUS*]->(current:Invitation{ id:3 })
//find (current) node's predecessor which might pointing on it through VALID_INVITATIONS or PREVIOUS relationships
OPTIONAL MATCH (u)-[oldValidRel:VALID_INVITATIONS]->(current)
OPTIONAL MATCH (predecessor:Invitation)-[oldPredecessorRel:PREVIOUS]->(current)
//find (current) node's subsequent node
OPTIONAL MATCH (current)-[oldSubsequentRel:PREVIOUS]->(subsequent:Invitation)
//first we re-create connections in list pointed by VALID_INVITATION relationship for consistency
WITH *, CASE subsequent WHEN NULL THEN [] ELSE [1] END AS hasSubsequent
//if (current) node is connected to (u) User we replace VALID_INVITATIONS relationship
FOREACH(_ IN CASE oldValidRel WHEN NULL THEN [] ELSE [1] END |
DELETE oldValidRel
//if (subsequent) node exist then we need to re-link it
FOREACH(_ IN hasSubsequent |
MERGE (u)-[:VALID_INVITATIONS]->(subsequent)
DELETE oldSubsequentRel
)
)
//following condition should be XOR with the one above (only one must be executed)
//if (current) node has another Invitation node as predecessor in list
FOREACH(_ IN CASE oldPredecessorRel WHEN NULL THEN [] ELSE [1] END |
DELETE oldPredecessorRel
//if (subsequent) node exist then we need to re-link it
FOREACH(_ IN hasSubsequent |
MERGE (predecessor)-[:PREVIOUS]->(subsequent)
DELETE oldSubsequentRel
)
)
WITH u, current
//now it is time to move (current) node to beginning of the list pointed by INVALID_INVITATIONS relationship
MERGE (u)-[:INVALID_INVITATIONS]->(current)
WITH u, current
//find obsolete oldRel:INVALID_INVITATIONS relationship
MATCH (current)<-[:INVALID_INVITATIONS]-(u)-[oldRel:INVALID_INVITATIONS]->(oldInv)
DELETE oldRel
//link (current) with previously "first" node in INVALID_INVITATIONS list
MERGE (current)-[:PREVIOUS]->(oldInv)
推荐答案
获得一些乐趣和来自@cybersam的帮助
我想出了更短的解决方案:
After having some "fun" and assisstance from @cybersam I came up with much shorter solution:
MATCH (u:User)-[:VALID_INVITATIONS|PREVIOUS*]->(current:Invitation {id:4})
MATCH (predecessor)-[oldPredecessorRel:VALID_INVITATIONS|PREVIOUS]->(current)
OPTIONAL MATCH (current)-[oldSubsequentRel:PREVIOUS]->(subsequent)
CALL apoc.do.when(subsequent IS NOT NULL, "CALL apoc.create.relationship($p, $r, NULL, $s) YIELD rel RETURN rel", "", {p:predecessor, r:type(oldPredecessorRel), s:subsequent}) YIELD value
DELETE oldPredecessorRel, oldSubsequentRel
WITH u, current
MERGE (u)-[:INVALID_INVITATIONS]->(current)
WITH u, current
MATCH (oldInv)<-[oldRel:INVALID_INVITATIONS]-(u)-[:INVALID_INVITATIONS]->(current)
DELETE oldRel
MERGE (current)-[:PREVIOUS]->(oldInv)
这篇关于密码查询,用于将节点从一种列表结构移动到另一种列表结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!