如何在进行广度优先搜索时在 Gremlin 中包含边?

Posted

技术标签:

【中文标题】如何在进行广度优先搜索时在 Gremlin 中包含边?【英文标题】:How to include edges in Gremlin while doing breadth first search? 【发布时间】:2014-05-26 09:56:57 【问题描述】:

在我的 gremlin 查询中,我有以下内容:

vert.as('x').
both.or(
  _().has("time").filter it.time.toInteger() > startTime.toInteger() ,
  _().has("isRead"), _().has("isWrite")).dedup().gather.scatter.
store(y).loop('x')c++ < limit.toInteger().iterate();

在我的 gremlin 脚本中,我返回 y,但 y 显然只有顶点。我可以通过为每个顶点迭代它们来手动检索每个边,但是我想要一个返回的列表,其中只包含在列表 y 中返回的其他节点之间的边。

特别是,我需要能够在本地重新创建在数据结构中返回的子图,因此使用 gremlin 来返回该信息。关于我的用例影响这些需求的其他细节是,手动迭代每个节点边缘太慢,因为我正在运行我的灯泡脚本的 rexster 服务器必须通过网络推送数据,而且还因为如果我没有使用脚本最初返回的每个顶点之间的边集,那么我必须检查沿每条边遇到的每个顶点,以确保它在最初返回的集合内;非常不理想。

基本上,任何结果都应该是这样的,当我查看任何返回的顶点时,我可以知道返回集合中链接了哪些顶点——而无需进行任何手动检查或查找。它应该只是在数据集中。

编辑 1:

我发现 gremlin 的树管道功能非常适合做我想做的事!问题是,既然我使用了tree,我需要将它返回到可以使用的形式......我只能返回顶点或边,所以我不能马上返回树。

编辑 2:

espeed 是对的;我应该使用bothE 开始。但是我有一些条件我想满足……我之前差点就有了,但是我无法让过滤器正常工作。

vert.as('l').
bothE.gather.scatter.as('edge').bothV.or(
  _().has("time").filter it.getProperty('time').toInteger() >= startTime.toInteger() ,
  _().has("isRead"), _().has("isWrite")).
dedup().store(results).as('vertice').back('edge').store(results).back('vertice')
.loop('l')c++ < limit.toInteger().iterate();

我不明白为什么我不能在一个管道中使用两个后端(我得到一个 NullPointerException 与这个管道)。我要解决的基本问题是:进行广度优先搜索,只存储满足以上所有条件的节点,并存储所有通过测试的顶点之间的边。

【问题讨论】:

【参考方案1】:

不要过多地弄乱你的代码,也许最简单的事情就是这样做:

results = [] as Set
vert.as('l').
bothE.as('e').gather.scatter.as('edge').bothV.or(
  _().has("time").filter it.getProperty('time').toInteger() >= startTime.toInteger().store(results),
  _().has("isRead"), _().has("isWrite")).store(results))
.sideEffecte,m->results<<m.e
.loop('l')c++ < limit.toInteger().iterate();

请注意,将结果声明为 Set 可以避免 dedup 步骤。基本上在or 步骤中过滤顶点时存储顶点。

【讨论】:

嗯,这非常接近我想要做的事情,而且我想我在一遍又一遍地编辑代码时做了类似的事情;这样做的问题是,当您执行 back('edge') 时,它会将结果从边缘转发到存储,但存储也只是将其传递。当循环获取当前元素值时,它是一条边,并且在 as('l') 处,它应该是一个顶点,以便让 bothE 解析。这就是为什么我不得不“支持”那里的碎片,但它总是抛出 NullPointerException... 移动 as('l') 并不能解决它;我认为唯一需要发生的是存储在 has("isWrite")).store(results) 的顶点需要是被发送回 as('l') 的顶点... 我摆脱了背部,只是通过命名边缘步骤并从 sideEffect 引用它来“欺骗”...这行得通吗?只是想让你得到一个答案,这样你就可以从那里迭代...也许这不是最好的方法。 这看起来正确,非常感谢,我不知道该怎么做,我什至研究过,但我不熟悉 Groovy。虽然看起来是对的,但是当我运行它时,即使我增加了限制,它似乎并没有增加更多的结果......我会回来看看为什么,它可能是我的数据...... 使用 Gremlin REPL 来编辑/调试 Gremlin 脚本(Rexster 不是为了那个)。理想情况下,您应该像测试 Python 脚本一样创建/测试 Gremlin 脚本——为代码创建 Gremlin-Groovy 文件并运行 Groovy 测试——这个流程要容易得多。然后,一旦您的 Gremlin 脚本工作,将其添加到灯泡。【参考方案2】:

使用bothE() 而不是both() 来访问边缘...

见http://gremlindocs.com/#transform/bothe

【讨论】:

再次感谢espeed。

以上是关于如何在进行广度优先搜索时在 Gremlin 中包含边?的主要内容,如果未能解决你的问题,请参考以下文章

在进行 ajax 调用时在 HTTP 标头中包含 JWT

树的广度优先搜索(上)

如何理解分支定界中广度优先搜索的内存问题

如何将列表单子函数转换为广度优先搜索?

NC15 求二叉树的层序遍历

如何在构建时在 C++ 中包含 JSON 文件/对象