Ограничение глубины запроса кратчайшего пути с помощью Gremlin на JanusGraph
У меня довольно большой график (в настоящее время 3806702 вершин и 7774654 ребер, все ребра с одинаковой меткой) в JanusGraph. Я заинтересован в поисках кратчайшего пути в нем. Рецепты Гремлин упоминают этот запрос:
g.V(startId).until(hasId(targetId)).repeat(out().simplePath()).path().limit(1)
Это возвращает путь, который я знаю, чтобы быть правильным, сразу же, но затем висит консоль (top
показывает, что janusgraph и scylla яростно обрабатывают вещи, поэтому, я думаю, это работает в фоновом режиме, но это занимает вечность). Он делает правильные вещи и возвращает первый (правильный) кратчайший путь, если используется так:
g.V(startId).until(hasId(targetId)).repeat(out().simplePath()).path().next()
Я хотел бы ограничить этот запрос так, чтобы gremlin/janusgraph прекратил поиск пути, скажем, через 100 прыжков (поэтому я хочу, чтобы максимальная глубина составляла 100 ребер). Я пытался использовать .times(100)
в нескольких положениях, но если .until()
используется с .times()
в одном и том же запросе всегда происходит сбой с NullPointerException в классах обхода gremlin, т.е.
java.lang.NullPointerException
at org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper.hasStepOfAssignableClassRecursively(TraversalHelper.java:351)
at org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy.apply(RepeatUnrollStrategy.java:61)
at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies.applyStrategies(DefaultTraversalStrategies.java:86)
at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.applyStrategies(DefaultTraversal.java:119)
at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.next(DefaultTraversal.java:198)
at java_util_Iterator$next.call(Unknown Source)
...
У кого-нибудь есть идеи, как я могу применить такой лимит? Мне нужно это, чтобы вернуть первый результат или потерпеть неудачу, быстро.
Спасибо!
1 ответ
Добавьте еще одно условие перерыва в вашем until()
а также убедитесь, что limit()
результат, прежде чем вы спросите пути:
g.V(startId).
until(__.hasId(targetId).or().loops().is(100)).
repeat(__.both().simplePath()).
hasId(targetId).limit(1).path()
призвание tryNext()
на этом обходе даст вам Optional<Path>
, Если он пуст, то в пределах заданного расстояния пути не найдено.