Gremlin查询以获取k个距离顶点和连接它们的边

时间:2019-06-26 12:20:18

标签: gremlin tinkerpop tinkerpop3

我想从给定的顶点开始,并获取所有连接的顶点和边,直到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个距离顶点和连接它们的边?

1 个答案:

答案 0 :(得分:2)

您可以将中断条件整合到内部重复遍历中,这使它变得更加容易:

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