Прежде всего, если у вас есть одна строка Gremlin с 100 или более шагами (конечно, не считая шагов анонимных дочерних переходов), я бы посоветовал вам пересмотреть свой подход в целом.Когда я сталкиваюсь с Гремлином такого размера, это обычно означает, что кто-то генерирует большой обход для того, чтобы каким-то образом поменять график.Это считается анти-паттерном, и его следует избегать, так как чем больше растет Gremlin, тем выше вероятность достижения пределов Xss
JVM для StackOverflowException
, а время прохождения компиляции, как правило, увеличивается и становится дорогим.Во многих случаях всего этого можно избежать, если каким-либо образом использовать inject()
или withSideEffect()
для передачи данных самого обхода, а затем использовать Gremlin в качестве цикла, который превращает эти данные в этапы мутации.В результате получается несколько более сложный оператор Gremlin, но он будет работать лучше и позволит избежать StackOverflowException
.
Во-вторых, обратите внимание, что этот обход, скорее всего, не будет работать так, как вы хотите, в любом поставщике графов - см. Этот примерна TinkerGraph:
gremlin> g.V().coalesce(hasId(1),constant('x'))
==>v[1]
==>x
==>x
==>x
==>x
==>x
gremlin> g.V().hasId(1)
==>v[1]
hasId()
внутри coalesce()
не будет оптимизирован графиком как быстрый поиск id
, а вместо этого будет рассматриваться как полное сканирование таблицы с фильтром.
В ответ на ваш вопрос я бы сказал, что самый простой вариант для вас - просто переместить valueMap()
внутрь coalesce()
:
g.V().coalesce(hasId("123").valueMap(false),
constant("ERROR - ID does not exist")).as("a").
V().coalesce(hasId("123").valueMap(false),
constant("ERROR - ID does not exist")).as("b").
select("a")
Я понимаю, почемуэто может быть плохо, если у вас много шагов, отличных от valueMap()
, потому что тогда вам приходится повторять одни и те же шаги снова и снова, делая код еще больше.Я думаю, это восходит к моему первому пункту.
Полагаю, вы могли бы использовать лямбду, хотя не все поставщики графов поддерживают это - обратите внимание, что я изменил ваш код, чтобы обеспечить поиск по id
с целью демонстрации:
gremlin> g.V(1).fold().coalesce(unfold(),map{throw new IllegalStateException("bad")})
==>v[1]
gremlin> g.V(10).fold().coalesce(unfold(),map{throw new IllegalStateException("bad")})
bad
В настоящее время я не уверен, что вы можете сделать что-то еще.Возможно, вы могли бы сделать «ошибку» Vertex
, которую вы могли бы вернуть в constant()
таким образом, valueMap()
сработало бы, но трудно сказать, будет ли это полезно, учитывая то, что я знаю об общем намерении вашего обхода.Я полагаю, вы могли бы придумать причудливую оценку «если-тогда», используя choose()
, но это может быть трудно читать и выглядеть неловко.Единственный другой вариант, который я могу придумать, - сохранить ошибку как побочный эффект:
gremlin> g.V(10).fold().coalesce(unfold(),store('error').by(constant('x'))).cap('error')
==>[x]
Я не думаю, что Гремлин дает вам действительно элегантный способ сделать то, что вы хотите прямо сейчас.