2015-11-02 3 views
3

У меня есть график с двумя определениями краев, как это:Arangodb пользовательского фильтра/посетитель моего графа дерева

isDepartment: [organisation] -> [organisation] 
hasAccess: [user] -> [organisation] 

организации вложены в дереве (без циклов). Существует несколько организаций верхнего уровня без каких-либо входящих isDepartment ребер.

Пользователи получают доступ к одной или нескольким организациям. Это могут быть организации или организации верхнего уровня, расположенные ниже по дереву. Если пользователь имеет доступ к организации, он имеет доступ ко всем дочерним организациям.

Я пытаюсь создать пользовательский посетитель или фильтр, который предоставляет мне все доступные организации для пользователя, включая его путь к корню, а также свойство, если они доступны или нет.

Например, возьмем следующую структуру организации:

  • корня
    • Средств А.1
    • Средств А.2
  • Корень Б
    • Департамент B.1
    • Департамент B.2
    • Субподготовка. B.2.1
  • Root C
    • Отдел C.1
    • Отдел С.2

Теперь возьмите пользователя, HasAccess к Root A и Dept. B.2. Я хотел бы, чтобы генерировать следующий результат: дерево

  • корня, доступный: истинный
    • Отдел A.1, доступный: истинный
    • Отдел А.2, доступный: истинный
  • Root B, доступны: ложные
    • Отдел В.2, доступный: истинный
    • Субдепт. B.2.1, доступный: истинный

Обратите внимание, что Root C и Dept. B1 не в результате, потому что они не доступны для пользователя, равно как и любой из их детей доступны.

Также обратите внимание, что Root B включен, но обозначен как not accessible. Это связано с тем, что пользователю предоставляется доступ только к ребенку Root B, но не к самому корню.

Как я могу написать пользовательскую функцию/посетитель/фильтр, которые это сделали?

ответ

5

Это действительно сложный вопрос, спасибо очень много;)

Вы можете решить эту проблему путем добавления функций, определяемых пользователем, чтобы AQL и использовать их в транспортер.

Прежде всего я зарегистрировал две функции AQL посетителя через arangosh:

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) 

Краткие: объяснения

  1. Найти организации этого пользователя имеет прямой доступ.
  2. Поднимитесь по дереву upwards и отметьте все как «noAccess».
  3. Спуститесь по дереву downwards и отметьте все как «доступ».
  4. Объединение upwards и downwards.

Если вы хотите изменить формат результата, вы должны изменить зарегистрированные функции посетителя.

+0

Ох, это выглядит очень хорошо. Спасибо, я собираюсь попробовать :-) –

+0

Это не совсем так, но я добираюсь туда. Мне нужно добавить некоторую сортировку и вложенность (или отступы на vertex.name), чтобы получить нужный мне результат. –