簡體   English   中英

Gremlin - 如何在不明確列出屬性的情況下合並頂點以組合它們的屬性?

[英]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的玩具圖表來展示它是如何完成的。

假設你想合並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]]

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 Kuppitzyouhans的回答,因為它給了我解決問題的基本思路。 但后來我發現該解決方案不適用於多行。 需要有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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM