Skip to content

Instantly share code, notes, and snippets.

@mrdanadams
Created March 28, 2012 21:40
Show Gist options
  • Save mrdanadams/2230825 to your computer and use it in GitHub Desktop.
Save mrdanadams/2230825 to your computer and use it in GitHub Desktop.
db.eval() and server-side updates on MongoDB with the Ruby driver
# Records the vote against 2 items.
# Both parameters are strings
def record_votes(winner_id, loser_id)
# grab the connection from the underlying driver
db = Mongoid::Config::master
# a future improvement would be to store this away somewhere, perhaps as a constant
# note: javascript comments added for the post: they are not in the real code
f = """
function(winner_id, loser_id) {
// will update one of the documents based on if it won the vote or not
var update = function(id, win) {
var doc = db.items.findOne({_id: ObjectId(id)});
if (!doc) return; // just ignore if can't find it
// updated automatically be Mongoid but we need to do it ourselves here
doc.updated_at = new Date();
// the simple updates that could have been done in-place
doc.votes++;
if (win) doc.wins++; else doc.losses++;
// stats calculations. the actual calculation is not important.
doc.percent_wins = Math.round(doc.wins / doc.votes * 100);
doc.percent_losses = Math.round(doc.losses / doc.votes * 100);
doc.rank = doc.percent_wins * (doc.votes >= #{ItemsController::VOTE_THRESHOLD} ? 100 : 10);
db.items.save(doc);
}
// perform separate updates on each document
update(winner_id, true);
update(loser_id, false);
}
"""
# note $eval has to be first
db.command({:$eval => f, args: [winner_id, loser_id], nolock: true})
end
> db.runCommand({ $eval: function(abool) { return abool; }, args: [false], nolock: true });
Tue Nov 22 11:55:02 [conn1] query test.$cmd ntoreturn:1 command: { $eval: function (abool) {
return abool;
}, args: [ false ], nolock: true } reslen:62 183ms
{ "retval" : false, "ok" : 1 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment