Запрос Гремлина для получения k вершин расстояния и соединяющих их ребер

Я хочу начать с заданной вершины и получить все связанные вершины и ребра на расстоянии k. Выходные данные должны включать все ребра, которые соединяют включенные вершины (даже если это ребро находится на расстоянии k + 1), чтобы у нас был полный подграф.

Представьте, что у нас есть это:

g.addV('person').property('name', 'a').as('va')
 .addV('person').property('name', 'b').as('vb')
 .addV('person').property('name', 'c').as('vc')
 .addV('person').property('name', 'd').as('vd')
 .addV('person').property('name', 'e').as('ve')
 .addV('person').property('name', 'f').as('vf')
 .addV('person').property('name', 'g').as('vg')
 .select('va').addE('knows').to('vb')
 .select('vb').addE('knows').to('vc')
 .select('vc').addE('knows').to('vd')
 .select('vd').addE('knows').to('ve')
 .select('ve').addE('knows').to('va')
 .select('ve').addE('knows').to('vf')
 .select('vf').addE('knows').to('vg')

https://i.stack.imgur.com/OYEBpm.png

a->b->c->d->e->(a) и e->f->g

Если мы начнем с c с расстояния 2, у нас должно получиться

a->b->c->d->e->(a)

С этим запросом

g.V().has('person','name','c')
     .repeat(bothE().dedup()
                    .store("e")
                    .bothV()
                    .dedup()
                    .store("v"))
     .times(2)
     .cap('e','v')

Я могу получить a->b->c->d->e, но мы теряем e->a край

С этим запросом

g.V().has('person','name','c')
     .repeat(bothE().dedup()
                    .store("e")
                    .bothV()
                    .dedup()
                    .store("v"))
     .times(2)
     .bothE()
     .dedup()
     .store('e')
     .cap('e','v')

мы получаем дополнительные ребра, которые соединяют внешние вершины, но мы также получаем ребро, которое соединяет внешнюю вершину f. Мы получаем a->b->c->d->e->(a), но также e->f

Как мы можем получить только k удаленных вершин и ребер, соединяющих их?


person PedroF    schedule 26.06.2019    source источник
comment
Кажется, это работает, хотя с некоторыми дублированными краями: gV (). Has ('person', 'name', 'c'). SideEffect (repeat (bothE (). Dedup (). Aggregate ('e'). BothV ( ) .dedup (). aggregate ('v')). times (2) .bothE (). dedup (). where (__. inV (). where (within ('v'))). where (__. outV (). где (внутри ('v'))). aggregate ('e')). cap ('v', 'e')   -  person PedroF    schedule 26.06.2019


Ответы (1)


Вы можете интегрировать условие разрыва во внутренний повторный обход, что немного упростит его:

g.V().has('person','name','c').store('v').
  repeat(bothE().where(without('e')).
         choose(loops().is(lt(2)),
                  aggregate('e'),
                  filter(otherV().where(within('v'))).aggregate('e').not(identity())).
         otherV().where(without('v')).aggregate('v')).
  cap('e','v')

На вашем образце графика:

gremlin> g.V().has('person','name','c').store('v').
......1>   repeat(bothE().where(without('e')).
......2>          choose(loops().is(lt(2)),
......3>                   aggregate('e'),
......4>                   filter(otherV().where(within('v'))).aggregate('e').
......5>                   not(identity())).
......6>          otherV().where(without('v')).aggregate('v')).
......7>   cap('e','v').sideEffect {
......8>      m = it.get()
......9>      println 'Vertices:'
.....10>      m.get('v').each {
.....11>        println "* " + it.value('name')
.....12>      }
.....13>      println 'Edges:'
.....14>      m.get('e').each {
.....15>        println "* " + [it.outVertex(), it.inVertex()]*.value('name').join(' -> ')
.....16>      }
.....17>   }.iterate()
Vertices:
* c
* d
* b
* e
* a
Edges:
* c -> d
* b -> c
* d -> e
* a -> b
* e -> a
person Daniel Kuppitz    schedule 26.06.2019
comment
Не могли бы вы объяснить, почему повторение прекращается? Он останавливается, когда больше нет ребер для пересечения? Вот почему not (identity ())? - person PedroF; 27.06.2019
comment
Точно. not (identity ()) просто фильтрует все. - person Daniel Kuppitz; 27.06.2019