如何获得包含满足特定条件的所有顶点的子图 [英] How to get a subgraph consisting of all vertices, that satisfy specific condition

查看:65
本文介绍了如何获得包含满足特定条件的所有顶点的子图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Document Revision 是位于我们域逻辑特定层中的两个对象.

The Document and the Revision are two objects that reside in our domain logic specific layer.

文档表示您可能想到的任何实质性纸张的抽象.也就是说-每个合同,发票或工程图都可以称为 Document .

The Document represents an abstraction around any material piece of paper that you could think of. That is - every contract, invoice or drawing could be called a Document.

另一方面,文档的材料表示形式是 Revision :建筑工程师在现场收到的纸质清单代表了 Revision设计者创建的文档.如果由于错误或需求变更而需要更改工程图中的某些内容,则新的修订将显示在站点上-同一 Document 修订#2 .

On the other hand, the material representation of the Document is the Revision: the list of paper, that construction engineer receives on site, represents a Revision of the Document that designer has created. If something in a drawing has to be changed, due to an error or changed requirements, then a new revision will show up on site - Revision #2 of the same Document.

修订版可能包含指向其他 Documents 的链接;因此,我们可以描述汽车,其门,发动机,车轮等之间的关系,以及每个元素独立发展而又与其他元素保持联系的可能性.

The Revision could contains links to other Documents; thus we could describe the relations between a car, its doors, engine, wheels and so on, and the possibility every element to evolve independently, while stays attached to other elements.

显示典型的 DAG :

我设法使用 C#图形API将所有顶点和边插入CosmosDB中. 我设法遍历该图并执行简单的查询,以查找该车有多少个版本,或者在最初创建时该发动机是否具有涡轮增压器. 但是,我正在努力编写一个复杂的查询,该查询仅返回每个零件或汽车的最新修订版本,或者返回直到2016-08-10的汽车状态的查询.

I managed to inset all vertices and edges into CosmosDB using C# Graph API. I managed to traverse the graph and execute simple queries in order to find how many revisions the car has, or if the engine has a turbocharger when it was initially created. However, I'm struggling with composing a complex query, that returns only the more recent revisions of every part or the car, or a query that returns the state of the car up to 2016-08-10.

截至2017年1月3日的汽车状态:

The state of the car up to 2017-01-03:

截至2016-08-10的汽车状态:

The state of the car up to 2016-08-10:

当遍历访问顶点的后代(其"out()")时,我无法找到一种方法来获取最新创建的内容并继续遍历而又不深入其他对象.如果您建议我一个表达式,该表达式仅返回图片中的彩色顶点,请多谢.

When the traversal visits the descendants of an vertex (its "out()"), I couldn't find a way to get the most recently created and to continue traversing without digging into the others. I will be grateful if you suggest me an expression, that returns only colored vertices from the pictures.

推荐答案

尽管图片很有用,但在询问有关Gremlin的问题时,始终提供可以生成图形样本的Gremlin脚本会很有帮助.例如,对于您的问题:

While pictures are helpful, when asking questions about Gremlin it is helpful to always provide a Gremlin script that can generate a sample of your graph. For example, for your questions:

graph = TinkerGraph.open()
g = graph.traversal()
g.addV('car').property('name','car').as('car').
  addV('rev').property('name','car revision 1').property('date', 1470787200L).as('carV1').
  addV('rev').property('name','car revision 2').property('date', 1472688000L).as('carV2').
  addV('frontLeftDoor').property('name','front left door').as('frontLeftDoor').
  addV('frontRightDoor').property('name','front right door').as('frontRightDoor').
  addV('engine').property('name','engine').as('engine').
  addV('turbocharger').property('name','turbocharger').as('turbocharger').
  addV('rev').property('name','front left door revision 1').property('date',1470787200L).as('frontLeftDoorV1').
  addV('rev').property('name','front left door revision 2').property('date',1472688000L).as('frontLeftDoorV2').
  addV('rev').property('name','front right door revision 1').property('date',1470787200L).as('frontRightDoorV1').
  addV('rev').property('name','engine revision 1').property('date',1470787200L).as('engineV1').
  addV('rev').property('name','engine revision 2').property('date',1472688000L).as('engineV2'). 
  addV('rev').property('name','engine revision 3').property('date',1483401600L).as('engineV3').
  addV('rev').property('name','turbocharger revision 1').property('date',1470787200L).as('turbochargerV1'). 
  addV('rev').property('name','turbocharger revision 2').property('date',1472688000L).as('turbochargerV2'). 
  addE('relates').from('car').to('carV1').
  addE('relates').from('car').to('carV2').
  addE('relates').from('carV1').to('frontLeftDoor').
  addE('relates').from('carV1').to('frontRightDoor').
  addE('relates').from('carV1').to('engine').
  addE('relates').from('carV2').to('frontLeftDoor').
  addE('relates').from('carV2').to('frontRightDoor').
  addE('relates').from('carV2').to('engine').
  addE('relates').from('frontLeftDoor').to('frontLeftDoorV1').
  addE('relates').from('frontLeftDoor').to('frontLeftDoorV2').
  addE('relates').from('frontRightDoor').to('frontRightDoorV1').
  addE('relates').from('engine').to('engineV1').
  addE('relates').from('engine').to('engineV2').
  addE('relates').from('engine').to('engineV3').
  addE('relates').from('engineV2').to('turbocharger').
  addE('relates').from('engineV3').to('turbocharger').
  addE('relates').from('turbocharger').to('turbochargerV1').
  addE('relates').from('turbocharger').to('turbochargerV2').iterate()

回答问题的人通常花更多的时间来创建问题的示例图,而不是开发提供答案的Gremlin.

It often takes the person answering the question more time to create a sample graph for the question than it does to develop the Gremlin that provides the answer.

无论如何,这是使用"2016年8月10日"作为开始日期"的一种方法:

Anyway, here is one way to do this using "8/10/2016" as the "start date":

gremlin> g.V().has('name','car').
......1>   repeat(local(out().has('date',lte(1470787200L)).
......2>                order().
......3>                  by('date',decr).limit(1)).
......4>          out()).
......5>     emit().
......6>   local(out().has('date',lte(1470787200L)).
......7>         order().
......8>           by('date',decr).limit(1)).
......9>   tree().by('name')
==>[car:[car revision 1:[front right door:[front right door revision 1:[]],engine:[engine revision 1:[]],front left door:[front left door revision 1:[]]]]]

这是一次遍历,但日期不同-"1/1/2017":

Here's the same traversal with a different date - "1/1/2017":

gremlin> g.V().has('name','car').
......1>   repeat(local(out().has('date',lte(1483228800L)).
......2>                order().
......3>                  by('date',decr).limit(1)).
......4>          out()).
......5>     emit().
......6>   local(out().has('date',lte(1483228800L)).
......7>         order().
......8>           by('date',decr).limit(1)).
......9>   tree().by('name')
==>[car:[car revision 2:[front right door:[front right door revision 1:[]],engine:[engine revision 2:[turbocharger:[turbocharger revision 2:[]]]],front left door:[front left door revision 2:[]]]]]

在这种情况下,请注意引擎版本3"被排除在外,因为它是"1/1/2017"之后的唯一顶点-树的其余部分都存在.

In this case, see that "engine revision 3" is excluded as it's the only vertex after "1/1/2017" - the rest of the tree is present.

一些注意事项:

  1. 为了方便比较,我将您的日期转换为多头.我不确定CosmosDB是否相对于has()lte谓词对日期进行了很好的处理,但是如果这样做,您可能更喜欢走这条路线.
  2. repeat()步骤允许在树中进行任意深度遍历,但请注意,它包含的重复逻辑恰好位于emit()之后的逻辑之外-这将捕获最后的树的叶子",就像在repeat()内一样循环结束,因为没有更多的outE()可以遍历.
  3. repeat()中的逻辑看起来有些复杂,但是基本上只是说当前的文档"遍历所有修订",以降序对日期进行排序,并获取第一个.一旦它具有您所关心的日期所控制的最新版本,就可以遍历它所连接的任何其他文档.
  4. 在这种情况下,我使用了tree()步骤,因为CosmosDB似乎支持该步骤.看起来他们还不支持subgraph().从技术上讲,该步骤甚至在Apache TinkerPop C#Gremlin语言变体中也不支持-那里存在一些挑战,使得Java仅具有不幸的功能.幸运的是,数据的形状像树一样,因此tree()步骤似乎就足够了.
  1. I converted your dates to longs for easier comparison. I'm not sure if CosmosDB has nice handling for dates with respect to the lte predicate for has() but if it does you would probably prefer going that route.
  2. The repeat() step allows for arbitrary depth traversal in the tree, but note the duplicated logic it contains just outside of that after emit() - this grabs the final "leaves of the tree" as inside the repeat() the loop ends because there are no more outE() to traverse.
  3. The logic within the repeat() looks a bit complex, but it's basically just saying for the current "document" traverse to all the "revisions", sort on the date in descending order and grab the first one. Once it has the most recent revision as controlled by the date you care about, traverse out to any other documents it is connected to.
  4. I used tree() step in this case as CosmosDB seems to support that. It does not look as though they yet support subgraph(). That step technically isn't even supported in the Apache TinkerPop C# Gremlin Language Variant - there are some challenges there that leave that a Java only features unfortunately. Luckily, the shape of your data is tree-like so tree() steps seems sufficient.

在Groovy中,您可以通过闭包提供重复的逻辑,以使事情更可重用:

In Groovy, you could supply the repeated logic by way of a closure to make things a bit more re-usable:

gremlin> traverseAndFilter = { out().has('date',lte(1470787200L)).
......1>                       order().
......2>                         by('date',decr).limit(1) }
==>groovysh_evaluate$_run_closure1@1d12e953
gremlin> g.V().has('name','car').
......1>   repeat(local(traverseAndFilter()).out()).
......2>     emit().
......3>   local(local(traverseAndFilter())).
......4>   tree().by('name')
==>[car:[car revision 1:[front right door:[front right door revision 1:[]],engine:[engine revision 1:[]],front left door:[front left door revision 1:[]]]]]

或存储'traverseAndFilter遍历本身并clone()遍历:

or store the 'traverseAndFilter" traversal itself and clone() it:

gremlin> traverseAndFilter = out().has('date',lte(1470787200L)).
......1>                       order().
......2>                         by('date',decr).limit(1);[] 
gremlin> g.V().has('name','car').
......1>   repeat(local(traverseAndFilter.clone()).out()).
......2>     emit().
......3>   local(local(traverseAndFilter.clone())).
......4>   tree().by('name')
==>[car:[car revision 1:[front right door:[front right door revision 1:[]],engine:[engine revision 1:[]],front left door:[front left door revision 1:[]]]]]

这篇关于如何获得包含满足特定条件的所有顶点的子图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆