Neo4j更新了一对多的关系

时间:2017-05-16 04:19:57

标签: neo4j cypher

我正在尝试更新两个节点之间的关系。节点类型为:

  1. 角色
  2. 权限即可。
  3. 关系名称是

    • HAS_PERMISSION 即可。

    我希望该查询适用于以下两种情况:

    情景A。添加新关系

    当PUT请求向API传递新的权限名称时,应发生以下情况:

    • 状态admin-[:HAS_RELATIONSHIP]->create

    • 请求许可['create', 'update'](查询时的requestPermissions)

    • 下一个州admin-[:HAS_RELATIONSHIP]->createadmin-[:HAS_RELATIONSHIP]->update

    情景B :删除关系

    • 国家admin-[:HAS_RELATIONSHIP]->createadmin-[:HAS_RELATIONSHIP]->update

    • 请求许可['update']

    • 下一个州admin-[:HAS_RELATIONSHIP]->update

    WITH [1]通过将其转换为列表来收集所有当前权限。 WITH [2]获取当前权限与获取应删除权限的请求所传递的权限之间的差异,并将当前权限转换为名称列表(其节点结构为{name : 'permission-name'}。WITH [3获取请求权限和获取应添加权限的当前权限之间的差异。然后删除并相应地添加节点。

    以下查询可以正常工作。它在场景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 
    

1 个答案:

答案 0 :(得分:1)

如果我可以简化您的问题,可以将方案A和B转换为方案C,作为"设置角色对此列表的权限"。就像那样,你只需要清理'预先存在的关系并写下新的关系。

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

更简单,更少可能出错。至于在同一个查询中组合DELETE和RETURN,这可能会有......奇怪的结果,因为Cypher是一个事务,而且Cypher的命令不能得到保证。因此,我建议仅在使用DELETE时返回已删除项目的计数(或者至少,只返回DELETE之前已匹配的项目,并且删除的项目可能为空)。