RethinkDB - 是否有更好的方法在嵌套数组上执行此非原子更新?
RethinkDB - is there a better way of doing this non-atomic update on a nested array?
我在 RethinkDB 数据库中有两个表 - "leagues" 和 "players",文档结构如下:
玩家
{
id: 1,
name: "Bob",
email: "bob@bob.com"
}
联赛
{
id: 1,
name: "L1",
standings: [{
"player_id": 1,
"position": 1
},{
"player_id": 2,
"position": 2
}]
}
我想要实现的是当玩家被删除时,有一个明显简单的 ReQL 查询来删除玩家:
r.table("players").get(1).delete().run(conn, callback);
但我还需要将该球员从他们正在参加的任何联赛中移除,然后更新该联赛中所有其他球员的位置,以便他们再次成为连续的。
这是我必须删除 ID 为“2”的玩家的查询:
r.table("leagues").getAll(2, { index: "player_id" }).update({
standings: r.row("standings").filter(function(standing) {
return standing("player_id").ne(2)
}).map(function(standing) {
return r.branch (
standing("position").gt(
r.table("leagues").getAll(2, { index: "player_id" }).nth(0)("standings").filter(function(s) {
return s("player_id").eq(2)
}).nth(0)("position")
),
standing.merge({ position: standing("position").sub(1) }),
standing
)
})
}, {
nonAtomic: true
})
这是有效的,它删除了被删除的玩家,然后洗牌剩余玩家的位置以填补空白并再次成为连续的。
我的问题是,有没有更好的方法?一个我不必将查询指定为非原子的?我只能认为我需要首先进行一些单独的查询,以找到我想要删除的玩家的位置,这样就可以将其作为变量而不是子查询传递,因为我相信这就是那部分正在使它成为非原子的。
干杯
我假设排名总是与数组中的位置匹配?
如果是这样,你可以这样写:
r.table('leagues').getAll(2, {index: 'player_id'}).update(function(row) {
return {
standings: row('standings').filter(function (standing) {
return standing('player_id').ne(2);
}.map(r.range(), function(standing, index) {
return standing.merge({position: index.add(1)});
})
};
});
如果没有,你可以这样写:
r.table('leagues').getAll(2, {index: 'player_id'}).update(function(row) {
return row('standings').filter(function (standing) {
return standing('player_id').eq(2);
}).nth(0)('position').do(function(pos) {
return {
standings: row('standings').filter(function (standing) {
return standing('player_id').ne(2);
}).map(function(standing) {
return r.branch(
standing('position').gt(pos),
standing.merge({position: standing('position').sub(1)}),
standing);
})
};
});
});
{
排名:行('standings').filter(函数(站立){
return 站立('player_id').ne(2)
}.map(r.range(), function(standing, index) {
return standing.merge({位置: index.add(1)});
})
};
})
我在 RethinkDB 数据库中有两个表 - "leagues" 和 "players",文档结构如下:
玩家
{
id: 1,
name: "Bob",
email: "bob@bob.com"
}
联赛
{
id: 1,
name: "L1",
standings: [{
"player_id": 1,
"position": 1
},{
"player_id": 2,
"position": 2
}]
}
我想要实现的是当玩家被删除时,有一个明显简单的 ReQL 查询来删除玩家:
r.table("players").get(1).delete().run(conn, callback);
但我还需要将该球员从他们正在参加的任何联赛中移除,然后更新该联赛中所有其他球员的位置,以便他们再次成为连续的。
这是我必须删除 ID 为“2”的玩家的查询:
r.table("leagues").getAll(2, { index: "player_id" }).update({
standings: r.row("standings").filter(function(standing) {
return standing("player_id").ne(2)
}).map(function(standing) {
return r.branch (
standing("position").gt(
r.table("leagues").getAll(2, { index: "player_id" }).nth(0)("standings").filter(function(s) {
return s("player_id").eq(2)
}).nth(0)("position")
),
standing.merge({ position: standing("position").sub(1) }),
standing
)
})
}, {
nonAtomic: true
})
这是有效的,它删除了被删除的玩家,然后洗牌剩余玩家的位置以填补空白并再次成为连续的。
我的问题是,有没有更好的方法?一个我不必将查询指定为非原子的?我只能认为我需要首先进行一些单独的查询,以找到我想要删除的玩家的位置,这样就可以将其作为变量而不是子查询传递,因为我相信这就是那部分正在使它成为非原子的。
干杯
我假设排名总是与数组中的位置匹配?
如果是这样,你可以这样写:
r.table('leagues').getAll(2, {index: 'player_id'}).update(function(row) {
return {
standings: row('standings').filter(function (standing) {
return standing('player_id').ne(2);
}.map(r.range(), function(standing, index) {
return standing.merge({position: index.add(1)});
})
};
});
如果没有,你可以这样写:
r.table('leagues').getAll(2, {index: 'player_id'}).update(function(row) {
return row('standings').filter(function (standing) {
return standing('player_id').eq(2);
}).nth(0)('position').do(function(pos) {
return {
standings: row('standings').filter(function (standing) {
return standing('player_id').ne(2);
}).map(function(standing) {
return r.branch(
standing('position').gt(pos),
standing.merge({position: standing('position').sub(1)}),
standing);
})
};
});
});
{ 排名:行('standings').filter(函数(站立){ return 站立('player_id').ne(2) }.map(r.range(), function(standing, index) { return standing.merge({位置: index.add(1)}); }) }; })