Gremlin - 如何合并顶点以组合其属性而不显式列出属性?

时间:2017-02-10 17:16:39

标签: titan gremlin tinkerpop3

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

enter image description here

我想获取给定身份节点的最新状态节点(红色)(蓝色)(由包含时间戳范围的“状态”边缘链接),但我想返回一个包含的聚合对象来自身份节点的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次往返的开销。我看过'聚合','联盟','折叠'等,但似乎没有做到这一点。

有什么想法吗?

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

编辑: 根据Daniel的回答(我不想做我想要的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]]

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

2 个答案:

答案 0 :(得分:7)

由于你没有提供我的示例图表,我将使用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]]

答案 1 :(得分:0)

使用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();