How to atomically replace document when it doesn't exists in Rethinkdb >= 1.11
-
21-12-2019 - |
Question
I've updated rethinkdb to 1.11.2 and found backward incompatibility in update/replace commands. In 1.10 both commands command returns proper response
r.db('test').table('user').get("notFound").update({a: 1}) // {"skipped": 1 ,...}
r.db('test').table('user').get("notFound2").replace({a: r.row('a').default(0).add(1)}) // {"inserted": 1 ,...}
but in 1.11.2 fails with an error:
RqlRuntimeError: Expected type OBJECT but found NULL. in:
r.db("test").table("user").get("notFound").update({a: 1})
I want to update a simple document atomically usnig single query (without checking if it exists).
Is there any way to execute the query in in rethinkdb >= 1.11 in the 1.10 way?
Solution
Note that I tried this: https://github.com/rethinkdb/rethinkdb/issues/209 but it threw a Runtime error about expecting an object but getting null. Here's how I did it for my logging table:
r.do(r.db('test').table('log').get('3333'), function(x) {
return r.branch(
x.eq(null),
r.db('test').table('log').insert({id: '3333', log: 'looool', c: 1}),
r.db('test').table('log').get('3333').update(function(l) { return {c: l('c').add(1)}; })
)
});
It's a bit verbose, but if the row doesn't exist it adds it, and if the row does exist, it increments its counter.
EDIT: Just upgraded from 1.11.1 to 1.11.3 and the original link works. I can now do:
r.db('test').table('log').get('3333').replace(function(x) {
return r.branch(
x.eq(null),
{id: '3333', log: 'haiii', c: 1},
x.merge({c: x('c').add(1)})
)
})
OTHER TIPS
If you are ok with the document being created if it doesn't exist (similar to replace
), you can use an upsert. See the upsert example here http://rethinkdb.com/api/javascript/insert/ .
UPDATE: I first thought upsert would behave like update
in case the document exist. But it does in fact behave like replace
, i.e. removing fields of the existing document if they are not in the one you provide to insert
.