Как я могу рекурсивно получить все дочерние вершины и их ребра (свойства для обоих) с помощью gremlin QL?

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

g.V().has("name","gremlin").outE().as('e').inV().as('v').select('e','v').by(valueMap())

Однако как мне сделать это рекурсивно, то есть для данной вершины, он будет проходить через всех своих дочерних элементов и возвращать каждую (вершину) и ее исходящее ребро (а) со всеми их свойствами (вершина и ребра) .... т.е. что-то вроде выше, но в цикле для каждой найденной дочерней вершины .... есть ли способ сделать это с помощью gremlin?


person nDev    schedule 14.05.2020    source источник


Ответы (1)


У Гремлин есть repeat() шаг, который вы можете использовать именно для этого. Вы можете повторять ... до и повторять .... раз и больше. В документации есть хорошие примеры. находится здесь: https://tinkerpop.apache.org/docs/current/reference/#repeat-step

Например

g.V().has("name","gremlin").
      repeat(outE().inV()).times(2).
      path().
        by(valueMap())

Обратите внимание, что возвращение всех свойств с использованием valueMap немного похоже на выполнение SELECT * в SQL, и в целом лучше возвращать только то, что вам действительно нужно, если набор результатов большой.

Если вы хотите получить обратно дерево, а не набор path результатов, вы можете использовать шаг tree. Ниже приведен пример использования TinkerGraph и простого графа двоичного дерева.

graph=TinkerGraph.open()
g=graph.traversal()

g.addV('root').property('data',9).as('root').
  addV('node').property('data',5).as('b').
  addV('node').property('data',2).as('c').
  addV('node').property('data',11).as('d').
  addV('node').property('data',15).as('e').
  addV('node').property('data',10).as('f').
  addV('node').property('data',1).as('g').
  addV('node').property('data',8).as('h').
  addV('node').property('data',22).as('i').
  addV('node').property('data',16).as('j').
  addV('node').property('data',7).as('k').
  addV('node').property('data',51).as('l').  
  addV('node').property('data',13).as('m'). 
  addV('node').property('data',4).as('n'). 
  addE('left').from('root').to('b').
  addE('left').from('b').to('c').
  addE('right').from('root').to('d').
  addE('right').from('d').to('e').
  addE('right').from('e').to('i').
  addE('left').from('i').to('j').
  addE('left').from('d').to('f').
  addE('right').from('b').to('h').
  addE('left').from('h').to('k').
  addE('right').from('i').to('l').
  addE('left').from('e').to('m').
  addE('right').from('c').to('n').
  addE('left').from('c').to('g').iterate()

gremlin> g.V().hasLabel('root').repeat(outE().inV()).times(2).tree()

==>[v[0]:[e[28][0-left->2]:[v[2]:[e[35][2-right->14]:[v[14]:[]],e[29][2-left->4]:[v[4]:[]]]],e[30][0-right->6]:[v[6]:[e[3
4][6-left->10]:[v[10]:[]],e[31][6-right->8]:[v[8]:[]]]]]]

gremlin> g.V().hasLabel('root').repeat(outE().inV()).times(2).
               tree().by(valueMap())

==>[[data:[9]]:[[]:[[data:[5]]:[[]:[[data:[8]]:[],[data:[2]]:[]]],[data:[11]]:[[]:[[data:[15]]:[],[data:[10]]:[]]]]]]

gremlin> g.V().hasLabel('root').repeat(outE().inV()).times(2).
               tree().by(valueMap().with(WithOptions.tokens))

    ==>[[id:0,label:root,data:[9]]:[[id:28,label:left]:[[id:2,label:node,data:[5]]:[[id:35,label:right]:[[id:14,label:node,da
    ta:[8]]:[]],[id:29,label:left]:[[id:4,label:node,data:[2]]:[]]]],[id:30,label:right]:[[id:6,label:node,data:[11]]:[[id:34
    ,label:left]:[[id:10,label:node,data:[10]]:[]],[id:31,label:right]:[[id:8,label:node,data:[15]]:[]]]]]]
person Kelvin Lawrence    schedule 14.05.2020
comment
Привет, да, я впоследствии видел это в вашей всеобъемлющей книге. Используя вышеизложенное, я не вижу того, чего ожидал. Скажем, моя иерархия состоит из двух уровней: A- ›e1-› B, A- ›e2-› C и C- ›e3-› D (т. Е. У A есть два дочерних элемента: B и У C и C есть дочерний элемент D, e - это ребра) вышеупомянутое дает мне что-то вроде [A, e1, C, e3, D]. Я ожидал, что он даст мне, начиная с A, его ребро с B, затем его ребро с C, а затем C и его ребро с D (включая, конечно, вершины) ... т.е. полное дерево ... кое-что, чего я не очень хорошо понял! - person nDev; 15.05.2020
comment
Хорошо, поэтому у Гремлина есть два шага, называемые tree () и subgraph (), которые здесь полезны. Обратите внимание: то, что вы видите, - это путь от каждого обходчика, который прошел по вашему графику, это не комбинированный результат. Если вы хотите получить комбинированный результат, взгляните на tree (). Добавлю к приведенному выше примеру. - person Kelvin Lawrence; 15.05.2020
comment
Кельвин, спасибо, что немного расширил мои знания (я еще не читал вашу книгу!). Я могу использовать tree, но я вижу, что когда я говорю times (2), это дает мне только ребра, которые переводят меня на второй уровень дерева. Это не дает мне первого уровня. Итак, по сути, если я не знаю глубины (т.е. не могу выполнить раз (x)), то как мне получить результат всего дерева с узлами, его дочерними элементами и ребрами? Я подозреваю, что все еще могу использовать tree ()? Огромное спасибо - person nDev; 15.05.2020
comment
Я пытаюсь вернуть все дерево одним запросом. Где я могу получить доступ к каждой вершине, ее ребрам и дочерним элементам. без необходимости писать вложенные циклы for для каждой вершины и т. д.! Спасибо - person nDev; 15.05.2020
comment
Если вы хотите продолжить обход, пока не попадете в листовой узел, вы можете просто заменить время (2), которое я только что использовал в качестве примера, чем-то вроде до (not (out ())) - person Kelvin Lawrence; 18.05.2020