Posts Tagged MongoDb

Mongoid, db.system.namespaces queries

Recently I faced some issues with Mongoid when upgrading my Rails app from REE+Passenger to MRI 1.9.3+Unicorn.

There are some Resque workers in the background. After some deploy they started to consume a ton of traffic from MongoDB. After some investigation, I found that they heavily read system.namespaces collection. I tried upgrading to latest versions of mongoid(2.4.3) and mongo(1.5.2) to no avail. This does not happen with normal unicorn workers. This also does not happen if I downgrade mongoid to 2.0.1.

I am still not sure what’s happening here. I’ll update this post when I discover something.

Tags: ,

Atomic updates, part 2

Let’s review another common scenario: posts and votes. Mongo’s approach would be to store vote count in the post itself (caching) and keep voters also in the post, in an array field. Let’s assume we want to register a new vote on post. This operation consists of three steps:

1. ensure that the voter hasn’t voted yet, and, if not,
2. increment the number of votes and
3. add the new voter to the array.

MongoDB’s query and update features allows us to perform all three actions in a single operation. Here’s what that would look like from the shell:

// Assume that story_id and user_id represent real story and user ids.
db.stories.update({_id: story_id, voters: {'$ne': user_id}}, 
  {'$inc': {votes: 1}, '$push': {voters: user_id}});

What this says is “get me a story with the given id whose voters array does not contain the given user id and, if you find such a story, perform two atomic updates: first, increment votes by 1 and then push the user id onto the voters array.”

This operation highly efficient; it’s also reliable. The one caveat is that, because update operations are “fire and forget,” you won’t get a response from the server. But in most cases, this should be a non-issue.

quote from MongoDB site.

How would you implement this in your regular SQL database?

Tags:

MongoId and atomic increment

I am starting to learn this new piece of technology, the MongoDB. It has many sweet features. However, using Ruby driver directly is not too comfortable. Plus we’re all hooked to ORM sweeteners. So people started developing ORM libraries for MongoDB and Ruby (MongoId, MongoMapper to name a few).

I have decided to try MongoId first. It seems to be a quite good library. However, it still has gaps in documentation. Today I was finding out how to perform an atomic increment of a field. In SQL world this would look like:

UPDATE users SET spam_count = spam_count + 1;

Mongo Ruby driver supports this kind of operation, but MongoId doesn’t. So I was trying to get down to the driver. And this is what I couldn’t easily find in the docs. If you’re like me, I’ll save you a couple of hours. Here it is:

# assume we know object id already
User.collection.update({'_id' => '4c05848e45760182b5000001'}, {'$inc' => {'spam_count' => 1}})

Tags: ,