【问题标题】:Why does the traversal result changes after a by-step and keeps only one result?为什么遍历结果一步步改变,只保留一个结果?
【发布时间】:2019-01-29 04:19:25
【问题描述】:

我正在构建一个 API 来获取和组织我的 janusgraph 数据库上的一些信息,但我对 gremlin 查询还比较陌生。我想知道为什么组步的第二步中的遍历会返回一些关于图的不完整信息

查询是从 gremlin python 驱动程序发送的,就好像它们是 gremlin 查询一样。起初我认为问题与它有关,但后来我直接从 gremlin 终端尝试(从 bin/gremlin.sh 运行),结果是一样的,所以我认为这不是一个错误,而是如何它的目的是。没关系,但我想了解为什么查询会导致这种情况,以及如何构建符合我需求的查询。

在示例中,我只对项目步骤使用了一个步骤,但在实际问题中,我打算使用多个步骤,如下所示:

(...).project('key1', 'key2', 'key3').by(...).by(...).by(...)

初始配置:

gremlin> g.V().has('name', 'fiber')
==>v[1]
==>v[2]

gremlin> g.V(1).in()
==>v[10]

gremlin> g.V(2).in()
==>v[20]


gremlin> g.V().has('name', 'fiber').in()
==>v[10]
==>v[20]

这就是我得到的:

gremlin> g.V().has('name', 'fiber').group().by('name').by(project('amount').by(__.in().count()))
==>{fiber={amount=1}}

gremlin> g.V().has('name','fiber').group().by('name').by(__.in().count())
==>{fiber=2}

gremlin> g.V().has('name', 'fiber').group().by('name').by(__.in())
==>{fiber=v[20]}

gremlin> g.V().has('name', 'fiber').group().by('name')
==>{fiber=[v[1], v[2]]}

这正是我所期待的:

gremlin> g.V().has('name', 'fiber').group().by('name').by(project('amount').by(__.in().count()))
==>{fiber={amount=2}}

gremlin> g.V().has('name','fiber').group().by('name').by(__.in().count())
==>{fiber=2}

gremlin> g.V().has('name', 'fiber').group().by('name').by(__.in())
==>{fiber=[v[10], v[20]]}

gremlin> g.V().has('name', 'fiber').group().by('name')
==>{fiber=[v[1], v[2]]}

【问题讨论】:

    标签: graph gremlin tinkerpop3 graph-traversal


    【解决方案1】:

    如您所见,这只是 Gremlin 中的一种设计选择,而不是错误。 by() 调制器仅在作为其参数传递的匿名 Traversal 上调用 next(),除非您明确告诉它,否则不会费心将整个事物迭代到列表中。我没有特别回忆by(Traversal) 以这种方式工作的所有原因,但一般来说,我认为 Gremlin 假设用户希望匿名遍历完成尽可能少的工作会更安全。如果你想让它做更多,那么你告诉 Gremlin 你想让它做更多。

    所以对于这个例子:

    g.V().has('name', 'fiber').group().by('name').by(__.in())
    

    如果您想要所有 in() 顶点,那么您需要告诉 Gremlin 明确收集:

    g.V().has('name', 'fiber').group().by('name').by(__.in().fold())
    

    请注意,by() 并不是唯一能以这种方式工作的步骤,Gremlin 所做的工作可能最少这一事实实际上是一种方便,可以减少输入,就像 emit() 调制器用于repeat() 步骤:

    g.V().repeat(out()).emit(outE())
    

    除了打字少,读起来也比:

    g.V().repeat(out()).emit(outE().limit(1).count().is(1))
    

    我还认为,by()(以及其他以 Traversal 为参数的步骤/调制器)以这种方式运行,Gremlin 不会过多假设您希望数据在结果。如果 Traversal 总是完全迭代,这意味着你总是会得到一个 List 作为输出,这可能是你想要的,也可能不是你想要的。然后你就可以打开并扔掉这个列表——所以 Gremlin 会创建一个对象只是为了把它扔给 GC。

    by() 的工作方式可能还有其他原因(主要是更具体的原因),但希望这个解释能让您对它的原因有所了解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-03
      • 2023-04-03
      • 2016-08-18
      • 1970-01-01
      • 2018-06-28
      • 1970-01-01
      • 1970-01-01
      • 2016-02-26
      相关资源
      最近更新 更多