【问题标题】:Gremlin - how do you merge vertices to combine their properties without listing the properties explicitly?Gremlin - 如何在不明确列出属性的情况下合并顶点以组合它们的属性?
【发布时间】:2017-06-29 03:20:18
【问题描述】:

背景:我正在尝试使用 gremlin (tinkerpop v3) 使用 this approach 实现时间序列版本数据库。

我想获取给定身份节点(蓝色)(由包含时间戳范围的“状态”边缘链接)的最新状态节点(红色),但我想返回一个聚合对象,其中包含来自身份节点的 id (cid) 和来自状态节点的所有属性,但我不想明确列出它们。 (8640000000000000 是我表示没有“到”日期的方式 - 即边缘是当前的 - 与显示的图像略有不同)。

我已经走到这一步了:

:> g.V().hasLabel('product').
     as('cid').
     outE('state').
     has('to', 8640000000000000).
     inV().
     as('name').
     as('price').
     select('cid', 'name','price').
     by('cid').
     by('name').
     by('price')

=>{cid=1, name="Cheese", price=2.50}
=>{cid=2, name="Ham", price=5.00}

但正如您所见,我必须列出“状态”节点的属性 - 在上面的示例中,产品的名称和价格属性。但这将适用于任何域对象,所以我不想一直列出属性。我可以在此之前运行查询来获取属性,但我认为我不需要运行 2 个查询,并且有 2 次往返的开销。我看过“聚合”、“联合”、“折叠”等,但似乎没有这样做。

有什么想法吗?

====================

编辑: 根据丹尼尔的回答(这并不能完全满足我想要的 ATM),我将使用他的示例图。在“modernGraph”人员创建-> 软件中。如果我跑:

> g.V().hasLabel('person').valueMap()
==>[name:[marko], age:[29]]
==>[name:[vadas], age:[27]]
==>[name:[josh], age:[32]]
==>[name:[peter], age:[35]]

然后结果是具有属性的实体列表。我想要的是,假设一个人只能创建一个软件(尽管希望我们稍后会看到如何为创建的软件列表打开它),将创建的软件“语言”属性包含到返回要获取的实体:

> <run some query here>
==>[name:[marko], age:[29], lang:[java]]
==>[name:[vadas], age:[27], lang:[java]]
==>[name:[josh], age:[32], lang:[java]]
==>[name:[peter], age:[35], lang:[java]]

目前最好的建议如下:

> g.V().hasLabel('person').union(identity(), out("created")).valueMap().unfold().group().by {it.getKey()}.by {it.getValue()}
==>[name:[marko, lop, lop, lop, vadas, josh, ripple, peter], lang:[java, java, java, java], age:[29, 27, 32, 35]]

我希望这更清楚。如果没有,请告诉我。

【问题讨论】:

    标签: titan gremlin tinkerpop3


    【解决方案1】:

    由于您没有提供我的示例图,我将使用 TinkerPop 的玩具图来展示它是如何完成的。

    假设你想合并markolop

    gremlin> g = TinkerFactory.createModern().traversal()
    ==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
    gremlin> g.V(1).valueMap()
    ==>[name:[marko],age:[29]]
    gremlin> g.V(1).out("created").valueMap()
    ==>[name:[lop],lang:[java]]
    

    请注意,有两个name 属性,理论上您将无法预测哪个name 会进入您的合并结果;但是,这在您的图表中似乎不是问题。

    获取两个顶点的属性:

    gremlin> g.V(1).union(identity(), out("created")).valueMap()
    ==>[name:[marko],age:[29]]
    ==>[name:[lop],lang:[java]]
    

    合并它们:

    gremlin> g.V(1).union(identity(), out("created")).valueMap().
               unfold().group().by(select(keys)).by(select(values))
    ==>[name:[lop],lang:[java],age:[29]]
    

    更新

    感谢您添加示例输出。这使得提出解决方案变得更加容易(尽管我认为您的输出包含错误;vadas 没有创建任何内容)。

    gremlin> g.V().hasLabel("person").
               filter(outE("created")).map(
                 union(valueMap(),
                       outE("created").limit(1).inV().valueMap("lang")).
                 unfold().group().by {it.getKey()}.by {it.getValue()})
    ==>[name:[marko], lang:[java], age:[29]]
    ==>[name:[josh], lang:[java], age:[32]]
    ==>[name:[peter], lang:[java], age:[35]]
    

    【讨论】:

    • 谢谢!我认为 identity() 调用是我在文档中错过的调用。不幸的是,我在我的图表和“现代”图表上都尝试了这个,我得到“没有这样的属性:类的键:groovysh_evaluate”。有任何想法吗?直到最后一个的所有查询都按照您上面的答案解决。
    • 您使用的是哪个 TinkerPop 版本?它可能比我用于测试的那个要旧。 IIRC 旧版本有 .mapKeys().mapValues(),请尝试使用它们。
    • 啊是的... Tinkerpop 3.0.1-incubating 我正在使用titanDb。您对 mapKeys() 等的看法是正确的,但这并不是我得到的直接替换:gremlin> gV(1).union(identity(), out("created")).valueMap().unfold().group() .by(select(mapKeys())).by(select(mapValues())) 没有方法签名:静态 org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select() 适用于参数类型:(org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal) 值:[[MapKeysStep]]
    • 在阅读了导致“选择”起源的问题后,也尝试了“by(mapKey‌​s()).by(mapV‌​alues())”,但没有任何乐趣。我不清楚这些运算符预期或返回的类型,我不确定在哪里查看 - 文档似乎没有达到这个级别或细节,否则我会遗漏一些东西。有任何想法吗? (抱歉给您添麻烦了!:-( )
    • 是的,3.0.1 的实现在这方面确实很弱。我找不到没有 lambda 的方法。但是,使用 lambdas 它是:....group().by {it.getKey()}.by {it.getValue()}.
    【解决方案2】:

    使用 gremlin java DSL 合并边和顶点属性:

     g.V().has('User', 'id', userDbId).outE(Edges.TWEETS)
        .union(__.identity().valueMap(), __.inV().valueMap())
        .unfold().group().by(__.select(Column.keys)).by(__.select(Column.values))
        .map(v -> converter.toTweet((Map) v.get())).toList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 2020-09-14
      • 2021-01-08
      相关资源
      最近更新 更多