[英]Gremlin - how do you merge vertices to combine their properties without listing the properties explicitly?
背景:我正在嘗試使用 gremlin(tinkerpop v3)使用這種方法來實現時間序列版本數據庫。
我想獲取給定身份節點(藍色)的最新 state 節點(紅色)(由包含時間戳范圍的“狀態”邊緣鏈接),但我想返回一個包含 id 的聚合 object( cid) 來自身份節點和來自 state 節點的所有屬性,但我不想明確列出它們。 (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}
但正如您所看到的,我必須列出“狀態”節點的屬性——在上面的示例中,產品的名稱和價格屬性。 但這將適用於任何域 object 所以我不想一直列出屬性。 我可以在此之前運行一個查詢來獲取屬性,但我認為我不需要運行 2 個查詢,並且有 2 個往返的開銷。 我看過“聚合”、“聯合”、“折疊”等,但似乎沒有這樣做。
有任何想法嗎?
====================
編輯:基於丹尼爾的回答(這並不完全符合我的要求)我將使用他的示例圖。 在“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]]
我希望這更清楚。 如果沒有,請告訴我。
由於您沒有提供我的示例圖表,我將使用TinkerPop的玩具圖表來展示它是如何完成的。
假設你想合並marko
和lop
:
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]]
UPDATE
感謝您添加的示例輸出。 這使得提出解決方案變得容易得多(雖然我認為你的輸出包含錯誤; 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]]
使用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();
感謝Daniel Kuppitz
和youhans
的回答,因為它給了我解決問題的基本思路。 但后來我發現該解決方案不適用於多行。 需要有local
步驟來處理多行。 修改后的 gremlin 查詢將如下所示:
g.V()
.local(
__.union(__.valueMap(), __.outE().inV().valueMap())
.unfold().group().by(__.select(Column.keys)).by(__.select(Column.values))
)
這會將 union 和 group by 的 scope 限制為單行。
如果您可以使用自定義 DSL,請像這樣使用 java 創建自定義 DSL。
public default GraphTraversal<S, LinkedHashMap> unpackMaps(){
GraphTraversal<S, LinkedHashMap> it = map(x -> {
LinkedHashMap mapSource = (LinkedHashMap) x.get();
LinkedHashMap mapDest = new LinkedHashMap();
mapSource.keySet().stream().forEach(key->{
Object obj = mapSource.get(key);
if (obj instanceof LinkedHashMap) {
LinkedHashMap childMap = (LinkedHashMap) obj;
childMap.keySet().iterator().forEachRemaining( key_child ->
mapDest.put(key_child,childMap.get(key_child)
));
} else
mapDest.put(key,obj);
});
return mapDest;
});
return it;
}
並像自由地使用它
g.V().as("s")
.valueMap().as("value_map_0")
.select("s").outE("INFO1").inV().valueMap().as("value_map_1")
.select("s").outE("INFO2").inV().valueMap().as("value_map_2")
.select("s").outE("INFO3").inV().valueMap().as("value_map_3")
.select("s").local(__.outE("INFO1").count()).as("value_1")
.select("s").outE("INFO1").inV().value("name").as("value_2")
.project("val_map1","val_map2","val_map3","val1","val2")
.by(__.select("value_map_1"))
.by(__.select("value_map_2"))
.by(__.select("value_1"))
.by(__.select("value_2"))
.unpackMaps()
結果到行
map1_val1, map1_val2,.... ,map2_va1, map2_val2....,value1, value2
這可以以自然的 gremlin 方式處理值和 valueMaps 的混合。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.