比方说,我有一个巨大的gremlin查询,包含100或更多的步骤。此查询的一部分失败,我希望它返回有意义的错误消息。简短而甜美的查询就不会太困难,因为我们可以执行以下操作:
g.V().coalesce(hasId("123"), constant("ERROR - ID does not exist"))
当然,我们要问的是是否存在ID为123的顶点。如果不存在,则返回一个字符串。
现在让我们来看这个例子,使其更复杂
g.V().coalesce(hasId("123"), constant("ERROR - ID does not exist")).as("a").V().coalesce(hasId("123"), constant("ERROR - ID does not exist")).as("b").select("a").valueMap(false)
如果存在ID为“ 123”的顶点,我们将返回存储在该顶点上的所有属性。
让我们说一个ID为“ 123”的顶点在数据库中不存在。如何在不对尝试对字符串执行.valueMap()的类型错误的情况下返回有意义的错误?
答案 0 :(得分:4)
首先,如果您只有一行Gremlin,且步数为100或更多(当然不算匿名子遍历步骤),建议您重新检查一下总体方法。当我遇到这么大的Gremlin时,通常意味着有人为了进行某种形式的图形变异而正在生成较大的遍历。这被认为是一种反模式,随着Gremlin的增大,达到Xss
的{{1}} JVM限制的机会也就越多,遍历编译时间会加起来并变得昂贵,因此应避免这种情况。在许多情况下,可以通过使用StackOverflowException
或inject()
以某种方式在遍历本身上传递数据,然后使用Gremlin作为将数据迭代为突变步骤的循环,来避免所有这些情况。结果是Gremlin语句稍微复杂一些,但是会更好地执行,并且避免使用withSideEffect()
。
第二,请注意,这种遍历可能不会在任何图形提供程序上按照您希望的方式运行-请在TinkerGraph上查看此示例:
StackOverflowException
图形不会将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")
以外的许多步骤,那可能会很糟糕,因为那样一遍又一遍地重复相同的步骤,会使代码变得更大。我想这可以回到我的第一点。
我想您可以使用lambda,尽管并非所有图形提供程序都支持该lambda-请注意,我已修改您的代码以确保通过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()
对if-then进行漂亮的评估,但这可能很难阅读且看起来很尴尬。我唯一想到的另一种选择是将错误存储为副作用:
choose()
我不认为Gremlin会给您任何真正优雅的方式来做您现在想要的事情。