我正在尝试更新两个节点之间的关系。节点类型为:
关系名称是
我希望该查询适用于以下两种情况:
情景A。添加新关系
当PUT请求向API传递新的权限名称时,应发生以下情况:
状态:admin-[:HAS_RELATIONSHIP]->create
请求许可:['create', 'update']
(查询时的requestPermissions)
下一个州:admin-[:HAS_RELATIONSHIP]->create
和admin-[:HAS_RELATIONSHIP]->update
情景B :删除关系
国家:admin-[:HAS_RELATIONSHIP]->create
和admin-[: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
答案 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之前已匹配的项目,并且删除的项目可能为空)。