在嵌套字段上应用增量值
Apply delta values on nested fields
假设我有这样的记录:
{
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
}
}
是否可以一次查询完成?
您想要通用的还是特定的?
具体很简单,这是通用案例:
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'))
)
这里可能有一些错误,因为它未经测试,但解决方案的关键点是 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
}
}))
假设我有这样的记录:
{
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
}
}
是否可以一次查询完成?
您想要通用的还是特定的? 具体很简单,这是通用案例:
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'))
)
这里可能有一些错误,因为它未经测试,但解决方案的关键点是 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
}
}))