我有一个包含两个边缘定义的图形:
isDepartment: [organisation] -> [organisation]
hasAccess: [user] -> [organisation]
组织嵌套在树中(无循环)。有多个顶级组织没有任何传入的isDepartment
边缘。
授予用户访问一个或多个组织的权限。这些可以是位于树下的某个顶层组织或组织。如果用户可以访问组织,则可以访问所有子组织。
我正在尝试构建一个自定义访问者或过滤器,为用户提供所有可访问的组织,包括它到根的路径,以及属性(如果它们可访问或不可访问)。
示例,采用以下组织结构:
现在请访问Root A
和Dept. B.2
的用户。我想生成以下结果树:
请注意,Root C
和Dept. B1
不在结果中,因为用户无法访问它们,也无法访问任何子级。
另请注意,Root B
已包含但标记为not accessible
。这是因为只允许用户访问Root B
的孩子而不是根本身。
如何编写完成此功能的自定义函数/访客/过滤器?
答案 0 :(得分:5)
这确实是一个具有挑战性的问题,非常感谢你;)
您可以通过向AQL添加用户定义的函数并在TRAVERSER中使用它们来解决此问题。
首先,我通过arangosh注册了两个AQL访问者函数:
var aqlfunctions = require("org/arangodb/aql/functions");
aqlfunctions.register("myvisitor::indirectAccess", "function (config, result, vertex) { if(result.length === 0) {result.push({});} result[0][vertex._key] = {hasAccess: true};}")
aqlfunctions.register("myvisitor::noAccess", "function (config, result, vertex) { if (result.length === 0) {result.push({});} result[0][vertex._key] = {hasAccess: false};}")
这些功能只需执行以下操作:
myvisitor::indirectAccess
将用于遍历树。与在AQL中一样,结果始终是一个数组,我们只是在它的第一个文档(如果需要)存储所有数据。然后我们为顶点_key
属性赋值{hasAccess: true}
。myvisitor::noAccess
将用于遍历树,并以相同的方式存储' {hasAccess:false}`。现在我们可以执行以下使用这些访问者的查询:
FOR x IN GRAPH_NEIGHBORS(@graph, @userId, {direction: 'outbound'})
LET upwards = TRAVERSAL(organisation, isDepartment, x, 'inbound', {visitor: 'myvisitor::noAccess'})[0]
LET downwards = TRAVERSAL(organisation, isDepartment, x, 'outbound', {visitor: 'myvisitor::indirectAccess'})[0]
RETURN MERGE(upwards, downwards)
简短的解释:
upwards
并将所有内容标记为" noAccess"。downwards
向下,将所有内容标记为"访问"。upwards
和downwards
。如果您想修改结果格式,您必须更改注册的访客功能。