我在一个小数据库上查询~10k条边和~2k个顶点
g.V("{}").repeat(outE().inV()).until(hasId(eq("{}")))
虽然这个查询有点蛮力,但是对于这么小的数据集,我希望它能很快获取。实际上它的结果是
Query cannot be completed due to memory limitations
这在这么小的数据集上是预期的吗?
图中的循环是很常见的,绝不应该总是被认为是错误。考虑A和B是朋友,B和A也是朋友的情况。
我们可以将其建模为:
(A)-FRIEND->(B)-FRIEND->(A)
这是一个完全合理的设计,因为我们可能想要考虑这样的情况,即a声称是B的朋友,但B还没有承认他们确实是a的朋友,所以,我们在每个方向上都有优势。然而,我们现在的数据中有一个循环。
上面描述的示例图可以使用以下命令创建:g.addV('A').as('a').
addV('B').as('b').
addE('FRIEND').from('a').to('b').
addE('FRIEND').from('b').to('a')
以你的例子为例,我们可能会想写这样的查询:
g.V().hasLabel('A').repeat(out()).until(hasId('X'))
然而,给定图中的循环,这本质上是一个无限循环,因为我们将不断访问A,B,A,B等,永远不会找到ID为X的顶点。
我们可以观察到&;无限循环&;使用timeLimit
步骤来中断查询,以阻止查询完全运行。
gremlin> g.V().hasLabel('A').repeat(timeLimit(1).out()).until(hasId('X')).emit()
==>v[1]
==>v[0]
==>v[1]
==>v[0]
==>v[1]
==>v[0]
==>v[1]
==>v[0]
==>v[1]
==>v[0]
==>v[1]
==>v[0]
==>v[1]
==>v[0]
==>v[1]
可以看到,查询被困在一个紧循环中。V[0]
为A, V[1]
为b,查询因时间限制而终止。
因此,我们需要编写查询代码来处理这些情况。执行此操作的两种最常见的方法是使用simplePath
或cyclicPath
,这取决于您是想捕获循环还是只是过滤掉包含循环的任何结果。
// No results as simplePath stops the traversal as soon as a cycle is found
gremlin> g.V().hasLabel('A').repeat(out().simplePath()).until(hasId('X')).path().by(label)
// We get a result as we stop after finding the cycle but include it in the results
g.V().hasLabel('A').repeat(out()).until(hasId('X').or().cyclicPath()).path().by(label)
==>[A,B,A]