Gremlin - переход к листовым узлам в древовидном графе

У меня есть древовидная структура данных в виде графика, как показано на диаграмме ниже. Каждый цвет представляет узел с разными метками с отношением, например, сотрудник -> приложение -> проект -> pv -> сканирование).

Вопрос №1:

Я хочу найти все листовые узлы (зеленые) верхнего узла 0.

Я пробовал ниже код с циклом, который возвращает все узлы с меткой сотрудника. Не только листовые узлы.

g.V().has('person', 'id', '0').repeat(__.in('reportsTo')).emit().values('id')

Образец графика можно найти в gremlinbin.

Как найти все узлы с зелеными листьями?

Обновление №1:

Как упоминалось в комментариях, я попробовал шаблон дерева. Но это не позволяет мне вызывать getLeafObjects () для дерева. Не уверен, чего не хватает. Кроме того, я снова могу создать дерево только узлов сотрудников. Как пройти к узлам сканирования?

> tree = g.V().has('person', 'id', '0').repeat(__.in('reportsTo')).emit().tree()
>  tree.getLeafObjects()
No signature of method: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal.getLeafObjects() is applicable for argument types: () values: []

Вопрос № 2:

Как мне получить дочернюю вершину среди дочерних элементов каждого родителя на основе max (id)? Итак, в моем примере графа каждая черная вершина может иметь одну или несколько зеленых дочерних вершин. Я хочу найти зеленые вершины с max (свойство) под каждой черной вершиной.

введите здесь описание изображения


person indusBull    schedule 11.01.2018    source источник
comment
Это все сканы. Это ваше определение зеленого? Этот список сканирований изначально был частью вашего вклада. Вы можете просто запросить метку вершины.   -  person Wolfgang Fahl    schedule 11.01.2018
comment
Это сработает, если я хочу найти все узлы сканирования под root. Но это не сработает, если я хочу найти все узлы сканирования под конкретным узлом сотрудника, а не только с корневым.   -  person indusBull    schedule 11.01.2018
comment
Вам может помочь github.com/tinkerpop/gremlin/wiki/Tree-Pattern есть вспомогательный метод получения листочков.   -  person Wolfgang Fahl    schedule 11.01.2018


Ответы (1)


Думаю, вам просто нужно изменить свой emit(). Без аргументов это говорит о том, что нужно испускать все из repeat(). Если вам нужны только листовые вершины, включите что-то вроде: not(outE()), которое в основном говорит, что излучать только в том случае, если на вершине нет исходящих ребер, что будет означать, что это вершина листа. Возможно, вам придется сделать свой конкретный emit() предикат немного умнее, поскольку похоже, что ваша схема такова, что разные типы вершин имеют разные правила для того, что может сделать его листом.

Учитывая образец графа, который у вас был в GremlinBin, я сделал это, чтобы получить все зеленые вершины в нижней части вашего изображения выше:

g.V().has('employee','id',1).
  repeat(__.in('reportsTo')).emit().
  repeat(out('has')).emit(__.not(outE('has')))

Отвечая на ваш второй вопрос, вы можете расширить приведенное выше на:

g.V().has('employee','id',1).
  repeat(__.in('reportsTo')).emit().
  repeat(out('has')).emit(__.not(outE('has'))).
  group().
    by(__.in('has')).
  select(values).
  unfold().
  order(local).
    by('id',decr).
  local(unfold().limit(1))

В основном сгруппируйте листовые вершины обратно на их родительскую вершину, а затем вытащите значения, которые представляют собой список листьев для каждого родителя. Сгладьте их с помощью unfold() и отсортируйте их по интересующему вас свойству (в данном случае «id»), а затем выберите первый элемент в этом упорядоченном списке.

person stephen mallette    schedule 11.01.2018
comment
мне все еще может быть непонятно, о чем вы спрашиваете, но я обновил свой ответ - это то, что вы ищете? - person stephen mallette; 11.01.2018
comment
Ваш пример запроса привел меня в правильном направлении. Я могу придумать запрос, чтобы вернуть желаемые результаты. Спасибо! Я добавил следующий вопрос в основную часть. Будет здорово, если вы дадите несколько советов. - person indusBull; 12.01.2018
comment
Я удалил свой первый комментарий. Я случайно вставил запрос с фактическим идентификатором :-( - person indusBull; 12.01.2018
comment
Спасибо, что работает отлично, хотя для обхода графа узлов 350K требуется 90 секунд. Придется заняться оптимизацией. - person indusBull; 12.01.2018
comment
У меня была почти такая же проблема, поскольку сеть поставщиков медицинских услуг владеет множеством больниц, а затем оттуда возникают ситуации с вспомогательными клиниками и я хочу пройти вниз из любой точки этого дерева, например, перечислить все учреждения и перечислить клиники, управляемые больницей. Это решает ту же проблему. +1 как по большому вопросу (graphcs очень помогли), так и по ответу. - person Manabu Tokunaga; 15.07.2021