【问题标题】:Query to retrieve all paths traversable from a given vertex查询以检索可从给定顶点遍历的所有路径
【发布时间】:2020-09-15 10:39:37
【问题描述】:

我正在尝试编写一个查询来检索从指定顶点可到达的所有路径。换句话说,我正在尝试检索顶点连接到的整个集群/子图。查询的更多限制是:

  1. 应遍历内边并将其包含在结果中(我正在寻找所有以任何方式连接到根顶点的路径。
  2. 搜索必须停止在指定的深度,例如,距离目标 10 跳 根顶点。
  3. 额外限制:我希望结果不包含作为结果中返回的其他路径的完整子路径的路径。

我目前有以下两个查询,它们似乎可以在我测试过的小型玩具图上正常工作。但是,在我们的大型生产图中似乎有一些边缘情况并没有返回我期望的所有路径/边缘/顶点,但我无法解释为什么会发生这种情况。这两个查询有时也会返回一些不同的顶点。

我希望对如何处理此查询有一个全新的看法,而不是尝试调整我目前拥有的内容,因此请先尝试提供解决方案,然后再查看下面我当前的解决方案。

查询 1:

g.V(uid).repeat(bothE().bothV().simplePath()).until(loops().is_(10)).emit().dedup().path().by(valueMap (真))

查询 2:

g.V(uid).repeat(bothE().bothV().simplePath()).until(bothE().simplePath().count().is_(0).or_().loops()。 is_(10)).dedup().path().by(valueMap(True))

【问题讨论】:

  • 您是要恢复所有路径(包含重复顶点)还是实际的子图结构?
  • 我愿意。 “子图结构”到底是什么意思?您是否打算使用实际的 Gremlin .subgraph() 函数?
  • Gremlin 有一个 subgraph 步骤,它将返回查询访问的子图 yes - 因此作为 path 的替代方案,如果您想排除任何部分,您可以选择返回子图路径重复。
  • 您能否提供一个查询来确保返回所有可到达的边/顶点?
  • 我在下面添加了一个答案,显示了pathsubgraph 的示例

标签: graph gremlin amazon-neptune


【解决方案1】:

使用这个简单的二叉树作为测试图

g.addV('root').property('data',9).as('root').
  addV('node').property('data',5).as('b').
  addV('node').property('data',2).as('c').
  addV('node').property('data',11).as('d').
  addV('node').property('data',15).as('e').
  addV('node').property('data',10).as('f').
  addV('node').property('data',1).as('g').
  addV('node').property('data',8).as('h').
  addV('node').property('data',22).as('i').
  addV('node').property('data',16).as('j').
  addV('node').property('data',7).as('k').
  addV('node').property('data',51).as('l').  
  addV('node').property('data',13).as('m'). 
  addV('node').property('data',4).as('n'). 
  addE('left').from('root').to('b').
  addE('left').from('b').to('c').
  addE('right').from('root').to('d').
  addE('right').from('d').to('e').
  addE('right').from('e').to('i').
  addE('left').from('i').to('j').
  addE('left').from('d').to('f').
  addE('right').from('b').to('h').
  addE('left').from('h').to('k').
  addE('right').from('i').to('l').
  addE('left').from('e').to('m').
  addE('right').from('c').to('n').
  addE('left').from('c').to('g').iterate()

我们可以使用

找到所有路径
gremlin>   g.V().hasLabel('root').
......1>   repeat(bothE().otherV().simplePath()).
......2>   until(__.not(bothE().simplePath())).
......3>   path().
......4>     by('data').
......5>     by(label) 

==>[9,right,11,left,10]
==>[9,left,5,left,2,left,1]
==>[9,left,5,left,2,right,4]
==>[9,left,5,right,8,left,7]
==>[9,right,11,right,15,left,13]
==>[9,right,11,right,15,right,22,left,16]
==>[9,right,11,right,15,right,22,right,51]   

请注意,我使用了bothE().otherV(),正如您所说的,在您的情况下,您可能有一些传入边缘以及传出边缘。

我们还可以使用subgraph 步骤返回包含顶点和边的整个子图。此示例查找从值为 5 的顶点开始的子树。

gremlin>   g.V().has('data',5).
......1>   repeat(bothE().subgraph('sg').otherV().simplePath()).
......2>   until(__.not(bothE().simplePath())).
......3>   cap('sg') 
==>tinkergraph[vertices:14 edges:13]  

请注意,这两种方法都假定所有路径都在叶节点处结束。我省略了loops() 测试,但您可以根据需要添加它。

【讨论】:

  • 谢谢。我正在使用gremlin_python,所以不幸的是我不认为 subgraph 方法会起作用,因为我也需要边和顶点的属性。我将研究您的第一种方法,看看它与我现有的解决方案相比如何。我也见过SubgraphStrategy,我会看看我是否可以在这里使用它,但我认为您不能使用像 SubgraphStrategy 这样复杂的查询,只是简单的条件。
  • “请注意,这两种方法都假定所有路径都在叶节点处结束。”。我认为这对我不起作用,因为在我的图表中,以下示例在理论上是一个可能存在的子图。您的解决方案不会返回任何内容gremlify.com/inch15pmxli/1
  • 有没有像until(next_node_has_already_been_traversed) 那样做的事情? (但仍然包括该节点的边缘)
  • 你可以使用类似until(cyclicPath())的东西
  • 这给出了结果。您应该能够对此进行修改以获得您想要的确切结果(哪些边缘等)g.V().hasLabel('customer_1').repeat(bothE(). otherV()). until(__.not(outE()).or().cyclicPath()).path()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
相关资源
最近更新 更多