2017-11-18 92 views
0

假設我有這樣的記載:嵌套領域應用增量值

{ 
    id: 1, 
    statistics: { 
     stat1: 1, 
     global: { 
      stat2: 3 
     }, 
     stat111: 99 
    } 
} 

我想要更新記錄與對象:

{ 
    statistics: { 
     stat1: 8, 
     global: { 
      stat2: 6 
     }, 
     stat4: 3 
    } 
} 

它應該被添加到當前記錄德爾塔。因此,結果記錄應如下所示:

{ 
    id: 1, 
    statistics: { 
     stat1: 9, 
     global: { 
      stat2: 9 
     }, 
     stat4: 3, 
     stat111: 99 
    } 
} 

是否可以使用一個查詢進行此操作?

回答

1

你想要一些通用或特定的東西嗎? 具體是容易的,這是一般的情況:

const updateValExpr = r.expr(updateVal); 
const updateStats = (stats, val) => val 
    .keys() 
    .map(key => r.branch(
     stats.hasFields(key), 
     [key, stats(key).add(val(key))], 
     [key, val(key)] 
    )) 
    .coerceTo('object') 

r.table(...) 
.update(stats => 
     updateStats(stats.without('global'), updateValExpr.without('global')) 
      .merge({ global: updateStats(stats('global'), updateValExpr('global')) 
) 

有可能是這裏的一些錯誤sincce這是未經測試,但該解決方案的關鍵點是updateStats功能,事實上,你可以得到所有的按鍵與.keys()coerceTo('object')改造此陣:[['a',1],['b',2]]到這個對象:{ a: 1, b: 2 }

編輯: 你可以做到這一點遞歸,但成果有限堆棧(因爲你不能直接發送遞歸棧,他們解決在查詢實際上是建立:

function updateStats(stats, val, stack = 10) { 
    return stack === 0 
     ? {} 
     : val 
      .keys() 
      .map(key => r.branch(
       stats.hasFields(key).not(), 
       [key, val(key)], 
       stats(key).typeOf().eq('OBJECT'), 
       [key, updateStats(stats(key), val(key), stack - 1)], 
       [key, stats(key).add(val(key))] 
      )).coerceTo('object') 
} 

r.table(...).update(row => updateStats(row, r(updateVal)).run(conn) 

// test in admin panel 
updateStats(r({ 
    id: 1, 
    statistics: { 
     stat1: 1, 
     global: { 
      stat2: 3 
     }, 
     stat111: 99 
    } 
}), r({ 
    statistics: { 
     stat1: 8, 
     global: { 
      stat2: 6 
     }, 
     stat4: 3 
    } 
})) 
+0

我也試過這樣的事情。但這裏的問題是可能有很多嵌套字段(至少嵌套5個lvl)。 – Suvitruf

+0

固定它,它似乎在我寫的數據瀏覽器中工作。請注意,您應該將其插入「更新」部分 – RonZ

+0

尼斯。它完美的作品。謝謝^ _ ^ – Suvitruf