Azure cosmosdb 如何得到由满足特定条件的所有顶点组成的子图

Azure cosmosdb 如何得到由满足特定条件的所有顶点组成的子图,azure-cosmosdb,gremlin,tinkerpop3,gremlin-server,Azure Cosmosdb,Gremlin,Tinkerpop3,Gremlin Server,文档和修订版是驻留在域逻辑特定层中的两个对象 该文档代表了围绕您可以想到的任何重要纸张的抽象。也就是说,每一份合同、发票或图纸都可以称为一份文件 另一方面,文件的材料表示是修订版:施工工程师在现场收到的图纸列表表示设计师创建的文件的修订版。如果由于错误或变更的要求,图纸中的某些内容必须进行更改,则现场将显示新的版本-同一文件的第2版 修订可能包含指向其他文件的链接;因此,我们可以描述汽车、车门、发动机、车轮等之间的关系,以及每个元素独立演化的可能性,同时保持与其他元素的联系 将显示一个典型示例:

文档和修订版是驻留在域逻辑特定层中的两个对象

该文档代表了围绕您可以想到的任何重要纸张的抽象。也就是说,每一份合同、发票或图纸都可以称为一份文件

另一方面,文件的材料表示是修订版:施工工程师在现场收到的图纸列表表示设计师创建的文件的修订版。如果由于错误或变更的要求,图纸中的某些内容必须进行更改,则现场将显示新的版本-同一文件的第2版

修订可能包含指向其他文件的链接;因此,我们可以描述汽车、车门、发动机、车轮等之间的关系,以及每个元素独立演化的可能性,同时保持与其他元素的联系

将显示一个典型示例:

我成功地将所有顶点和边插入到CosmosDB中。 我设法遍历了图表并执行了简单的查询,以便找到汽车有多少次修改,或者发动机在最初创建时是否有涡轮增压器。 然而,我正在努力编写一个复杂的查询,只返回每个零件或汽车的最新版本,或者返回2016-08-10之前汽车状态的查询

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

截至2016年8月10日的汽车状况:


当遍历访问某个顶点的后代(其“out()”)时,我无法找到一种方法来获取最近创建的顶点,并在不深入其他顶点的情况下继续遍历。如果您向我推荐一个表达式,该表达式只返回图片中的彩色顶点,我将不胜感激。

虽然图片很有用,但在询问有关Gremlin的问题时,始终提供一个可以生成图形示例的Gremlin脚本是很有帮助的。例如,对于您的问题:

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()
通常,回答问题的人为问题创建一个样本图所花费的时间比开发提供答案的小精灵所花费的时间要多

无论如何,这里有一种方法可以使用“8/10/2016”作为“开始日期”:

以下是不同日期的相同穿越——“2017年1月1日”:

在这种情况下,请参见“engine revision 3”被排除在外,因为它是“1/1/2017”之后的唯一顶点-树的其余部分存在

请注意:

  • 为了便于比较,我将你的日期转换为long。我不确定CosmosDB是否能够很好地处理
    lte
    谓词的
    has()
    日期,但如果是这样的话,您可能更愿意选择这条路线
  • repeat()
    步骤允许在树中进行任意深度遍历,但请注意,在
    emit()
    
  • repeat()
    中的逻辑看起来有点复杂,但它基本上只是说对于当前“文档”遍历到所有“修订版”,按降序排序日期并获取第一个。一旦它具有由您关心的日期控制的最新版本,则遍历到它所连接的任何其他文档
  • 我在本例中使用了
    tree()
    步骤,因为CosmosDB似乎支持这一点。看起来它们还不支持
    子图()
    。从技术上讲,Apache TinkerPop C#Gremlin语言变体甚至不支持这一步骤——不幸的是,存在一些挑战,导致Java只具备一些功能。幸运的是,数据的形状是树形的,因此
    tree()
    步骤似乎足够了
  • 在Groovy中,您可以通过闭包的方式提供重复的逻辑,以使事情更加可重用:

    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()
    它:

    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:[]]]]]
    

    很抱歉没有发布插入脚本!我下次一定会这样做!查询应该在文档的所有修订中找到指定日期之前的最新修订。它应该是这样的:获取当前文档的所有修订->OrderByDate->GetClosestAndNotGreatedThan date->继续使用Revisio所指的文档n已发现。如果存在早于2016-08-10的版本,则lte(1470787200L)也会采用这些版本。在上述示例中,第一个版本的日期偶然匹配。每个版本都可能有不同的日期,并且提供的日期(解决日期)是随机的。”树的解决方案“任何时候都可能发生。我想我复制/粘贴了一个旧版本的代码到我的答案中。我的示例图中甚至有错误的数据。不管怎样,我已经解决了两件事,我认为可以解决你的问题。我甚至用“2017年1月1日”添加了第二次遍历,以表明它不受任何特定日期的约束。谢谢您的帮助!我真的很感谢你的奉献!但是,我觉得我仍然无法澄清查询的预期行为。2017年1月1日的预期结果应为:[汽车],[汽车-修订2],[左前门-修订2],[右前门-修订1],[发动机-修订2],[涡轮增压器-修订2]。必须删除上次修订的版本。第二个查询返回2017年1月1日之前创建的所有修订,但我需要的只是其中的最后一个修订。
    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:[]]]]]
    
    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:[]]]]]