我不确定这种方法是否适用于 CosmosDB,但它很可能是您可以在 Gremlin 中实际采用的唯一方法,它不涉及多个 Gremlin 请求和额外处理。我使用这个示例图进行演示:
g = TinkerGraph.open().traversal()
g.addV().property(id,'A').as('a').
addV().property(id,'B').as('b').
addV().property(id,'C').as('c').
addV().property(id,'D').as('d').
addV().property(id,'E').as('e').
addV().property(id,'F').as('f').
addE('next').from('a').to('b').
addE('next').from('b').to('c').
addE('next').from('b').to('d').
addE('next').from('c').to('e').
addE('next').from('d').to('e').
addE('next').from('e').to('f').iterate()
该方法涉及使用group(),在每次循环通过repeat() 时,您基本上都会形成一个新的遍历对象分组:
gremlin> g.V('A').
......1> group('m').by(constant(-1)).
......2> repeat(out().group('m').by(loops())).
......3> cap('m')
==>[-1:[v[A]],0:[v[B]],1:[v[C],v[D]],2:[v[E],v[E]],3:[v[F],v[F]]]
这为您提供了要处理的数据结构,现在您只需要确保尽早终止 repeat():
gremlin> g.V('A').
......1> group('m').by(constant(-1)).
......2> until(cap('m').select(values).unfold().count(local).sum().is(gte(3))).
......3> repeat(out().group('m').by(loops())).
......4> cap('m')
==>[-1:[v[A]],0:[v[B]],1:[v[C],v[D]]]
在上面的示例中,我们查看until() 中的“m”,并对目前收集到的所有顶点进行计数。当它超过我们的最大值时,在本例中为“3”,我们退出。当我们退出时,我们可以看到我们可能收集到了比我们需要的更多的东西。在这个例子中我们做了,所以我们需要把它扔掉。从技术上讲,您需要除最后一个分组之外的所有分组来满足您的限制,但不幸的是,使用 Gremlin,“除最后一个分组之外的所有分组”并不容易。我最终采用了这种方法,它基本上抓住了最后一个要扔掉的项目,然后将其用作结果的过滤器。请注意,我们得到两个结果,因为遍历到下一个级别将超过我们的“3”个结果总数的限制:
gremlin> g.V('A').
......1> group('m').by(constant(-1)).
......2> until(cap('m').select(values).unfold().count(local).sum().is(gt(3))).
......3> repeat(out().group('m').by(loops())).
......4> cap('m').
......5> select(values).as('v').
......6> tail(local).as('e').
......7> select('v').unfold().
......8> where(P.neq('e')).
......9> unfold()
==>v[A]
==>v[B]
请注意,当我们从“3”限制增加到“4”时,结果会发生变化,因为遍历到下一个级别将在总数中增加 2,但总数不会超过 4。
gremlin> g.V('A').
......1> group('m').by(constant(-1)).
......2> until(cap('m').select(values).unfold().count(local).sum().is(gt(4))).
......3> repeat(out().group('m').by(loops())).
......4> cap('m').
......5> select(values).as('v').
......6> tail(local).as('e').
......7> select('v').unfold().
......8> where(P.neq('e')).
......9> unfold()
==>v[A]
==>v[B]
==>v[C]
==>v[D]
下一个示例指出,我们不考虑重复,因为从您的用例中不清楚预期的内容(或者这是否会起作用),但希望这为您提供了足够的结构,至少可以形成遍历您正在寻找:
gremlin> g.V('A').
......1> group('m').by(constant(-1)).
......2> until(cap('m').select(values).unfold().count(local).sum().is(gt(5))).
......3> repeat(out().group('m').by(loops())).
......4> cap('m').
......5> select(values).as('v').
......6> tail(local).as('e').
......7> select('v').unfold().
......8> where(P.neq('e')).
......9> unfold()
==>v[A]
==>v[B]
==>v[C]
==>v[D]
感谢 Kelvin Lawrence 提出我在此答案中采用的一般方法。