深入學習Gremlin(19):結果存取口袋sack

第19期 Gremlin Steps:

sack()

本系列文章的Gremlin示例均在HugeGraph圖數據庫上執行,環境搭建可參考準備Gremlin執行環境,本文示例均以其中的“TinkerPop關係圖”爲初始數據,如下圖所示:

init-data

上一期:深入學習Gremlin(18):隨機過濾與注入

結果存取口袋說明

Gremlin在路徑遊走的時候,可以將中間結果存放到一個叫口袋(sack)的結構裏面,以備在後續步驟中使用;此外在放入數據到口袋的時候,還可以做一些靈活的操作比如:分裂(split)、合併(merge)等。sack相關step屬於Gremlin語言裏面的高級操作,在處理較爲複雜的任務時可以靈活的實現一些特殊功能。

下面講解實現上述功能的具體Step:

  • withSack(): 創建一個口袋,並給定一個初始結構,比如可以是一個返回Map或者隨機數的lambda函數,也可以是一個對象或常數;另外還可以提供lambda分裂函數,以指定當traverser分裂時的行爲,比如進行clone操作。
  • sack(): 將數據放入口袋,或者從口袋取出數據。當傳入lambda合併函數作爲參數時,可指定放入口袋的行爲如何執行;當不傳入參數時表示讀取口袋中的內容。

實例講解

下面通過實例來深入理解每一個操作。

  1. Step withSack()…sack(): 利用口袋來存取結果

    示例1:

    // 創建一個包含常數1的口袋,
    // 並且在最終取出口袋中的值
    g.withSack(1).V().sack()
    

    g.withSack(1).V().sack()

    示例2:

    // 創建一個包含常數1的口袋,
    // 並且在最終取出口袋中的值
    g.withSack{new Random().nextFloat()}
     .V().sack()
    

    g.withSack{random}.V().sack()

    試一試:將g.withSack{}的大括號換爲小括號g.withSack()看看有什麼區別

    示例3:

    // 通過sum求和的方式把數據放入口袋
    g.withSack(0).V()
     .repeat(outE().sack(sum).by('weight').inV())
     .times(3).sack()
    

    g.withSack(0).V().sack(sum)

    試一試:通過以下gremlin查看路徑及其權重:

    g.withSack(0).V()
     .repeat(outE().sack(sum).by('weight').inV())
     .times(3).path().by().by('weight')
    

    示例4:

    // 通過lambda函數來指定放入口袋的行爲
    // 注意:提供的初始值爲Map類型,而且
    // 當traverser分裂時會拷貝Map
    g.withSack{[:]}{it.clone()}
     .V().out().out().dedup()
     .sack{m,v -> m[v.value('name')] = v.value('lang'); m}
     .sack()
    

    g.withSack{map}{clone}.V().sack(lambda)

    試一試:去掉分裂函數後看看效果:

    g.withSack{[:]}
     .V().out().out().dedup()
     .sack{m,v -> m[v.value('name')] = v.value('lang'); m}
     .sack()
    

    示例5:

    // 平均獲取口袋中的值
    g.withSack(1.0).V('javeme')
     .out('knows').out('created')
     .barrier(normSack).sack()
    

    g.withSack(1).V().barrier(normSack).sack()

綜合運用

  1. 獲取路徑並計算路徑權重之和

    // 獲取路徑的同時通過sack(sum)計算權重之和
    // 最終通過select把權重和路徑選取出來
    g.withSack(0).V()
     .repeat(outE().sack(sum).by('weight').inV().as('p'))
     .times(3).sack().as('w')
     .select('w', 'p').by().by{p->p.toString()}.limit(3)
    

    path-by-sum-weight

  2. 獲取路徑並根據路徑權重之和排序

    // 獲取路徑的同時通過sack(sum)計算權重之和
    // 最終通過order().by(sack())根據總權重排序
    g.withSack(0).V()
     .repeat(outE().sack(sum).by('weight').inV())
     .times(3).order().by(sack(),decr)
     .path().limit(3)
    

    path-order-by-sum-weight

下一期:深入學習Gremlin(20):barrier

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章