如何在Gremlin中返回有意义的错误?

如何在Gremlin中返回有意义的错误?,gremlin,tinkerpop,tinkerpop3,Gremlin,Tinkerpop,Tinkerpop3,假设我有一个包含100个或更多步骤的巨大的小精灵查询。此查询的一部分出现故障,我希望它返回一条有意义的错误消息。通过简短而甜蜜的查询,这不会太困难,因为我们可以这样做: g.V().coalesce(hasId("123"), constant("ERROR - ID does not exist")) 当然,我们要问的是ID为123的顶点是否存在。如果它不存在,我们将返回一个字符串 现在让我们以这个例子为例,让它变得更复杂 g.V().coalesce(hasId("123"), const

假设我有一个包含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()。

首先,如果您有一行包含100个或更多步骤的Gremlin(当然不包括匿名子遍历步骤),我建议您重新检查您的方法。当我遇到这种大小的小精灵时,通常意味着有人正在生成一个大的遍历,以便以某种方式改变图形。这被认为是一种反模式,需要避免,因为Gremlin越大,达到
StackOverflowException
Xss
JVM限制的可能性就越大,遍历编译时间越长,代价就越高。在许多情况下,通过以某种方式使用
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]
图不会将
coalesce()
中的
hasId()
作为快速
id
查找进行优化,而是将其视为带过滤器的完整表扫描

不过,在回答您的问题时,我想说,您可以选择的最简单的方法是将
valueMap()
移动到
coalesce()
中:

我明白了为什么除了
valueMap()
之外,还有很多其他的步骤,这可能是不好的,因为这样一来,您就需要一次又一次地重复相同的步骤,使代码变得更大。我想这可以追溯到我的第一点

我想您可以使用lambda,但并非所有图形提供程序都支持它-注意,为了演示,我修改了您的代码,以确保通过
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()
对if-then进行一个奇特的评估,但这可能很难理解,而且看起来很尴尬。我能想到的唯一其他选择是将错误存储为副作用:

gremlin> g.V(10).fold().coalesce(unfold(),store('error').by(constant('x'))).cap('error')
==>[x]

我不认为小精灵现在能给你任何优雅的方式去做你想做的事

首先,如果您有一行包含100个或更多步骤的小精灵(当然不包括匿名子遍历步骤),我建议您重新检查您的方法。当我遇到这种大小的小精灵时,通常意味着有人正在生成一个大的遍历,以便以某种方式改变图形。这被认为是一种反模式,需要避免,因为Gremlin越大,达到
StackOverflowException
Xss
JVM限制的可能性就越大,遍历编译时间越长,代价就越高。在许多情况下,通过以某种方式使用
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]
图不会将
coalesce()
中的
hasId()
作为快速
id
查找进行优化,而是将其视为带过滤器的完整表扫描

不过,在回答您的问题时,我想说,您可以选择的最简单的方法是将
valueMap()
移动到
coalesce()
中:

我明白了为什么除了
valueMap()
之外,还有很多其他的步骤,这可能是不好的,因为这样一来,您就需要一次又一次地重复相同的步骤,使代码变得更大。我想这可以追溯到我的第一点

我想您可以使用lambda,但并非所有图形提供程序都支持它-注意,为了演示,我修改了您的代码,以确保通过
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()
对if-then进行一个奇特的评估,但这可能很难理解,而且看起来很尴尬。我能想到的唯一其他选择是将错误存储为副作用:

gremlin> g.V(10).fold().coalesce(unfold(),store('error').by(constant('x'))).cap('error')
==>[x]

我不认为小精灵现在能给你任何优雅的方式去做你想做的事

谢谢你的回复。你的第一段谈到了小精灵反模式。关于这些反模式,你有什么好的阅读材料吗?Gr中增加了一个新的部分