How to see MongoDB index creation progress (easy)

At mongodb shell, you can show all current operations (queries, index, etc) using the following command:

db.currentOp();

If you just want to see the index creation process, you can filter it by using the following:

db.currentOp({ $or: [ { op: “query”, “query.createIndexes”: { $exists: true } }, { op: “insert”, ns: /\.system\.indexes\b/ } ] })

Advertisements

How to correctly increment a number in Rails [Handling Concurrency]

Scenario

Imagine you have a Visits collection at your rails application, and it has an attribute called counter. Every time an user visits one of your application’s page, the attribute gets incremented.

Wrong (Common) Way in MongoDB:

The common way of doing this would be:

This is bad because we are pulling the document from the database, putting it into our application’s memory, modifying it, and finally send it back to the database for persisting its changes. This whole operation could take some precious time.

If the counter is at 0, for example, and two users visit our app at the same time, both would add plus 1 at the same time, so we would end up with only 1 registered visit! This problem is multiplied by the application’s traffic size.

Right Way in MongoDB:

MongoDB has an atomic increment operator that handles the concurrency for us and the Mongoid gem lets us call it from our model’s instance. Just call the inc method and specify the amount you want to increment.

The inc accepts both positive and negative values as the incremental amount.

ActiveRecord

ActiveRecord provides the increment method for the same purpose.

More information at: apidock.com/rails/ActiveRecord/Base/increment!

 

 

[Dokku] How to dump and restore a Mongo Database.

In this tutorial, I will show how you can dump your production data and restore it at staging.

MongoDB

1- Log into your production server (replace productionip with your server’s ip):

ssh root@productionip

2- Dump your data (replace lolipop with your service name):

dokku mongo:export lolipop > lolipop.dump.tar

3- Go back to your local machine and copy the dump from the server:

scp root@productionip:/root/lolipop.dump.tar .

4- Send the dump to the staging machine (replace stagingip with your server’s ip):

scplolipop.dump.tar root@67.205.133.218:/root

5- Log into the staging server:

ssh root@stagingip

6- Restore the dump:

dokku mongo:import lolipop < lolipop.dump.tar

Done! Enjoy the ride.

[Rails concerns] Stop putting code into your ApplicationController!!

Sometimes people put too much stuff at the application controller, and they make all the others controllers inherit from it.

This is not a good pratice, since you can end up loading unnecessary helpers or whole gems at your API controllers for example, and losing performance.

Scenario

Let’s say, for example, that every user at your application has a integer field called visits, and it gets incremented every time the user visits a page. If you would have that in your application controller, it should look something like this:

Solution

Instead, you should extract specific functionalities to concerns and include them where and when you need it, letting the application controller as skinny as possible.

Concern:

Now you can include this code in every controller we need, making it more organized and explicit:

 

 

Mongoid: connecting to two databases

Scenario

Let’s say you have two collections at your Ruby on Rails application, users and urls. Now you want to save the users collection in one server, and the urls collection in another one.

Solution

First, add the second server configuration at config/mongoid.yml, as following:

Now you have a default client connection to the first server and have a second one called “secondary” to the other.

The other thing you need to do, is to tell your collection what client it should use. The users collection will use the default configuration, rails has that covered for us.

For the urls collection, your model should look like this:

Bonus

Sharded mongodb

If your secondary database is actually sharded across two or more servers, you need to list all the servers ips at mongoid.yml file and set the connection option to sharded:

And don’t forget to include the shard key at the url model:

All done, happy deploy!