简体   繁体   English

Neo4j更新一对多关系

[英]Neo4j update one-to-many relationship

I am trying to update a relationship between two Nodes. 我正在尝试更新两个节点之间的关系。 The node types are: 节点类型为:

  1. Role 角色
  2. Permission . 权限

The relationship name is 关系名称是

  • HAS_PERMISSION . HAS_PERMISSION

I would like the query to work for the following two scenarios: 我希望该查询适用于以下两种情况:

SCENARIO A. Add new relationship 场景A.添加新关系

When a new permission name is passed by PUT request to the API, the following should occur: 当PUT请求将新的权限名称传递给API时,将发生以下情况:

  • STATE : admin-[:HAS_RELATIONSHIP]->create admin-[:HAS_RELATIONSHIP]->create

  • PERMISSION PASSED BY REQUEST : ['create', 'update'] (requestPermissions on Query) 通过请求通过的权限['create', 'update'] (查询的requestPermissions)

  • NEXT STATE : admin-[:HAS_RELATIONSHIP]->create and admin-[:HAS_RELATIONSHIP]->update 下一个状态admin-[:HAS_RELATIONSHIP]->createadmin-[:HAS_RELATIONSHIP]->update

SCENARIO B : Delete Relationship 场景B :删除关系

  • STATE : admin-[:HAS_RELATIONSHIP]->create and admin-[:HAS_RELATIONSHIP]->update 状态admin-[:HAS_RELATIONSHIP]->createadmin-[:HAS_RELATIONSHIP]->update

  • PERMISSION PASSED BY REQUEST : ['update'] 权限通过请求['update']

  • NEXT STATE : admin-[:HAS_RELATIONSHIP]->update 下一个状态admin-[:HAS_RELATIONSHIP]->update

WITH [1] collects all current permissions by converting it to a list. WITH [1]通过将其转换为列表来收集所有当前权限。 WITH [2] gets the difference between the current permissions and the permissions passed by the request obtaining the permissions that should be deleted and it converts the current permissions into a list of names (its node structure is {name : 'permission-name'} . WITH [3] gets the difference between the request permissions and the current permissions obtaining the permissions that should be added. Then the nodes are deleted and added accordingly. WITH [2]获取当前权限和请求传递的权限之间的差,该权限获得应删除的权限,并将当前权限转换为名称列表(其节点结构为{name : 'permission-name'} 。WITH [3]获取请求权限和当前权限之间的差,获得应添加的权限,然后删除节点并相应地添加。

The following query does the work ok. 以下查询可以正常工作。 It works as expected on Scenario A but on Scenario B it does the job but it does not return anything. 它在方案A上可以正常工作,但在方案B上可以完成工作,但不返回任何内容。

MATCH (role:Role)-[:HAS_PERMISSION]->(permissions:Permission) 
WHERE id(role) = 7
SET role = {name: 'admin'}

WITH COLLECT(permissions) AS permissions, 
    ['update'] AS requestPermissions, 
    role

WITH FILTER(permission IN permissions WHERE NOT permission.name IN 
    requestPermissions) AS toDeletePermissions, 
    REDUCE(values = [], permission in permissions | values + 
       permission.name) as permissionsValues,
    requestPermissions,
    role, 
    permissions

WITH FILTER(permission IN requestPermissions WHERE NOT permission IN 
    permissionsValues) AS toAddPermissions, toDeletePermissions, role, 
    permissions

UNWIND (CASE toDeletePermissions WHEN [] THEN [null] ELSE 
    toDeletePermissions END) as permission
    OPTIONAL MATCH (role)-[rel:HAS_PERMISSION]->(permission)
    DELETE rel

WITH toAddPermissions, permissions, role

UNWIND  (CASE toAddPermissions WHEN [] THEN [null] ELSE 
  toAddPermissions END) AS permission
  MATCH (p:Permission {name: permission})   
  MERGE (role)-[:HAS_PERMISSION]->(p)

WITH role
MATCH (role)-[:HAS_PERMISSION]->(permissions:Permission)
RETURN role, permissions 

If I may simplify your problem, scenario A and B can be converted to scenario C as "Set role's permissions to this list". 如果我可以简化您的问题,则可以将方案A和B转换为方案C,作为“设置对此列表的角色权限”。 Like that, you just need to 'clean' the pre-existing relationships and write new ones. 这样,您只需要“清理”已有的关系并编写新的关系即可。

MATCH (role:Role)
WHERE id(role) = 7
SET role = {name: 'admin'}
WITH role, ['update'] as requestPermissions 

// Use optional so that absence of matches doesn't break anything
OPTIONAL MATCH (role)-[rel:HAS_PERMISSION]->(permission:Permission)
WHERE NOT permission.name IN requestPermissions 
DELETE rel

WITH DISTINCT role, requestPermissions
MATCH (permission:Permission)
WHERE permission.name IN requestPermissions
CREATE UNIQUE (role)-[:HAS_PERMISSION]->(permission)

// Return what we set
RETURN role, permission

Much simpler, and less that can go wrong. 更简单,更少出错。 As for combining DELETE and RETURN in the same query, this can have... weird.. results as the Cypher is one transaction, and the Order the Cypher is done is not guaranteed. 至于在同一查询中组合DELETE和RETURN,这可能会产生奇怪的结果,因为Cypher是一个事务,并且不能保证Order of the Cypher完成。 So I would recommend only returning the count of deleted items when using DELETE (or at the very least, only return what you have already matched before the DELETE, and deleted items may be empty). 因此,我建议仅在使用DELETE时返回已删除项目的计数(或者至少,仅返回在DELETE之前已经匹配的内容,并且已删除项目可能为空)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM