I want to update a field in a database table that has to have a cumulative value. So basically I need to find the current value of the field and update it using a new number.
My first inefficient try at this (in Mongoid) is:
v = Landlord.where(:name=>"Lorem")
v.update_attributes(:violations=>v.violations + 10)
Is there a simple method than making one query to read, then sum up, and another query to write?
MongoDB provides special atomic update operation support for exactly this scenario — take a look at the
$incmodifier in the Updating documentation. Your example in the plainmongoconsole would be:With Mongoid this would be:
This will set violations to 10 if the field is defined on your model but hasn’t otherwise been initialized to any value yet.
But actually, this still executes two queries (look up the landlord, then update it). To do it all in one, you need to go through a
Mongoid::Collectionobject, which proxies most calls straight through to the Mongo Ruby driver. That would look like this:It helps to be familiar with the Ruby driver for cases like this when you want to take more direct control. Its API tries to match closely with the
mongoJavascript shell syntax.