Rethinkdb原子操作

时间:2015-07-26 07:20:05

标签: rethinkdb atomicity

假设我有一份文件

{
    id: 1,
    fruits: []
}

这里的水果充当了SET

现在我希望原子为fruits数组添加一个值,使用primary key = 1 OR 创建这样的文件(如果它不存在)(即使用SetInsert ReQL)引擎盖)

我还需要为增量(ReQL .Add)

做同样的事情

显然这不能在客户端代码中完成,因为它打破了原子性,最终导致数据不一致

我希望这样的事情可能

r.table('results').insert({
  id: '62c70132-6516-4279-9803-8daf407ffa5c',
  counter: r.row('counter').add(1).default(0)
}, {conflict: "update"})

但它死于“RqlCompileError:r.row未在此上下文中定义”

感谢任何帮助/指导, 谢谢!

2 个答案:

答案 0 :(得分:7)

目前insert无法做到这一点。另一个提到的解决方案不是原子的,因为它使用子查询。 我们正在https://github.com/rethinkdb/rethinkdb/issues/3753中为此制定解决方案。

但是,您可以使用replace执行原子upsert:

r.table('results').get('62c70132-6516-4279-9803-8daf407ffa5c')
 .replace({
  id: '62c70132-6516-4279-9803-8daf407ffa5c',
  counter: r.row('counter').add(1).default(0)
})
如果文档不存在,

replace将实际执行插入。

答案 1 :(得分:3)

在RethinkDB中,所有单一查询更新都是原子的。如果Rethink认为特定的更新/替换操作不是原子的,则会抛出错误并要求您向查询添加非原子标记。通常情况下,您不必过于担心它。但是,仅适用于updatereplace个查询。使用insert原型无法做到这一点。

你是正确的,如果您检索该文档,请更新它的客户端,然后将其放回到数据库中,它本质上也是非原子更新。

但是,在单个查询中,您可以执行以下操作,这与您使用insert的方式相同,但使用replace

r.table('FruitStore')
.get(1)
.replace({
  id : 1, 
  fruits : r.row('fruits').default([]).append('orange') 
})

......这将是原子的。同样,要使用添加操作:

r.table('FruitStore')
.get(1)
.replace({
  id : 1, 
  count : r.row('count').default(0).add(1) 
})