微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么hasNot“复活”了一个死的遍历?

如何解决为什么hasNot“复活”了一个死的遍历?

我正在尝试创建一个遍历,添加一个顶点,然后从已知顶点添加一条边到新顶点。我有 a library method 使用 coalesce 来检查是否存在现有边缘(它不可能),如果不存在则添加它。但是,我可靠地将边添加到第一个子顶点,然后没有边添加到新子顶点。这是遍历:

gts.addV()... // add properties and such; this part reliably works
  .as('newV') // needed because I can't pass __addV() to the edge coalesce or I get two adds
  .V(parent)
  .coalesce(
    __.outE('Manages').where(inV().has(id,__select('newV').id())).hasNot(TTL_END),__.addE('Manages').to(__select('newV')).property(TTL_START,Now)
  )

当我分析这次遍历时,我发现添加第二个和后续子顶点时有些奇怪:

CoalesceStep([[VertexStep(OUT,[Manages],edge),...                     1           1           0.469    18.82
  VertexStep(OUT,edge)                                       1           1           0.020
  TraversalFilterStep([EdgeVertexStep(IN),Prof...                     1           1           0.188
    EdgeVertexStep(IN)                                                 1           1           0.010
    TraversalFilterStep([IdStep,ProfileStep,S...                                             0.091
      IdStep                                                           1           1           0.010
      SelectOnestep(last,newV)                                         1           1           0.020
      NoOpBarrierStep(2500)                                            1           1           0.019
      IdStep                                                                                   0.012
  NotStep([Propertiesstep([ttl.end],value),Pro...                     1           1           0.170
    Propertiesstep([ttl.end],value)                                                            0.008
EdgeVertexStep(IN)                                                     1           1           0.305    12.23

据我所知,这似乎是在说“id 过滤器”正在过滤掉不匹配的新孩子1,因此不返回任何遍历器(这就是我期望),但是随后 hasNot 步骤,我希望在接下来的管道中应用,弹出回到顶层,说“边缘(对第一个孩子)没有 {{1 }},所以我会归还它!”,ttl.end 接受了它,我没有把我的优势传给第二个孩子。

我的理解是,一旦遍历器“死亡”,额外的过滤步骤将被简单地作为多余的过滤步骤丢弃,并且不会通过遍历传播更多内容,但我期望作为 AND 过滤器的行为似乎是“复活”ID过滤器应该“杀死”的遍历器。

为什么 coalesce 会被遍历,即使它的上游过滤器不应该匹配?我怎样才能产生我想要的复合谓词?

(我也首先尝试了 NotStep 步骤,得到了相同的结果,步骤在配置文件输出中转置。)


1 第二个 `IdStep` 上根本没有任何遍历器是否表明存在问题?

解决方法

has(String,Traversal) 步骤可能是现存最被误用的步骤。用户期望它的意思是“将 Traversal 解析为一个值,并使该值与指定键进行相等比较”。但是,正如你所看到的,这不是它的作用:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6],standard]
gremlin> g.V().as('a').has(id,select('a'))
==>v[1]
==>v[2]
==>v[3]
==>v[4]
==>v[5]
==>v[6]

文档试图用这个来解释它(也许还有其他地方的解释/例子):

has(key,traversal):如果遍历器的对象没有通过属性值的遍历产生结果,则移除遍历器。

因此,在该上下文中,如果您将 select() 用于 Traversal 参数,请考虑会发生什么 - 它有效地忽略了作为遍历器的“属性值”,并从 {{ 的任何返回值中插入它自己的值1}}。除非您选择不存在的内容,否则它会返回一个值,因此过滤器通过。我们已经讨论过更改此行为,但担心会破坏依赖此功能的现有代码。也许它在未来可能会改变......

说了这么多,我想我会按如下方式重写您的遍历:

select()

嵌套的 gremlin> g = TinkerGraph.open().traversal() ==>graphtraversalsource[tinkergraph[vertices:0 edges:0],standard] gremlin> g.addV('person').property(id,'parent') ==>v[parent] gremlin> now = 100 ==>100 gremlin> g.addV('person').as('newV'). ......1> V('parent'). ......2> coalesce( ......3> __.outE('Manages').where(inV().where(eq('newV'))).hasNot("end"),......4> __.addE('Manages').to(__.select('newV')).property("start",now)) ==>e[1][parent-Manages->0] gremlin> g.addV('person').as('newV'). ......1> V('parent'). ......2> coalesce( ......3> __.outE('Manages').where(inV().where(eq('newV'))).hasNot("end"),now)) ==>e[3][parent-Manages->2] gremlin> g.E().property('end',101) ==>e[1][parent-Manages->0] ==>e[3][parent-Manages->2] gremlin> g.addV('person').as('newV'). ......1> V('parent'). ......2> coalesce( ......3> __.outE('Manages').where(inV().where(eq('newV'))).hasNot("end"),now)) ==>e[5][parent-Manages->4] 可能是表达此过滤器的更好方式。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。