I'm trying to update multiple documents in RethinkDB, based on some precalculated values in a Hash. i.e.
Given a table stats
with primary key slug
with data like
[{slug: 'foo', stats: {}}, {slug:'bar', stats:{}}]
and given a Hash with values like
updated_stats = {
'foo' => {a: 1, b: 2},
'bar' => {a: 3, b: 4}
}
I can do this
updated_stats.each{|k,v|
r.table('stats').get(k).update{|s|
{ :stats => v }
}
}
So, why can't I do the following?
r.table('stats').get_all(*updated_stats.keys).update{|s|
{ :stats => updated_stats[s["slug"]] }
}
the rql shows nil as the value of updated_stats[s["slug"]]. Would really appreciate any help on this. Thanks.
It's a tricky problem.
Here's the solution first.
r.table('stats').get_all(*updated_stats.keys).update{|s|
{ :stats => r.expr(updated_stats).get_field(s["slug"]) }
}.run()
Then updated_stats
is a ruby hash so when you use the brackets, it's the usual bracket operator, and since updated_stats
doesn't have the key s["slug"], it returns nil.
So you have to wrap updated_stats
in r.expr()
.
Then brackets in ruby are used for nth
, get_field
, slice
etc. And when given a variable, it cannot guess which one it should use.
So you have to explicitly say you want to use get_field
.
We will add a bracket term, which should fix this problem -- see https://github.com/rethinkdb/rethinkdb/issues/1179
Sorry you ran into this!
For anyone looking for how to bulk update records, it's actually pretty easy but not at all intuitive.
You actually have to perform an insert
while specifying that if there's any conflicts, to update those records. You will obviously need to provide the Id of each record to be updated.
Using the following data set:
|-------------|--------------|
| id | title |
|-------------|--------------|
| 1 | fun |
|-------------|--------------|
| 2 | in |
|-------------|--------------|
| 3 | the |
|-------------|--------------|
| 4 | sun |
|-------------|--------------|
Here's an example (javascript):
const new_data = [
{id: 1, title: 'dancing'},
{id: 4, title: 'rain'},
];
r.db('your_db').table('your_table').insert(new_data, {conflict: 'update'});
The results would be:
|-------------|--------------|
| id | title |
|-------------|--------------|
| 1 | dancing |
|-------------|--------------|
| 2 | in |
|-------------|--------------|
| 3 | the |
|-------------|--------------|
| 4 | rain |
|-------------|--------------|
One caveat you should be aware of, though, is that if you represent something in the new_data
array that doesn't currently exist in the table, it will be added/upserted.
Cheers!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With