MongoDB 201: setup troubleshooting and Query tips

** Post In Development **

Installation Gotchas

When I first installed Mongo it was for development on my Mac. During the bootup I got serveral small hurdles I had to figure out.

The first one was Mongod wouldn't start. That issue was just because I had forgot to make the /data/db directory that mongo needs to be able to write it's data to. If you do this just cd to your root and do a
sudo mkdir -p /data/db and make sure it's read and writeable by mongo. Since im on dev I just gave it 777 but you may not want to do that.

The second one is soft rlimits too low. Number of files is 256, should be at least 100 To solve this one at the command prompt just type: ulimit -n 2048 before you start the mongod server.

Last one I kept seeing was --rest is specified without --httpinterface. Funny that I was seeing this because I had actually aliased the mongod command to mongod --rest in my bash profile and forgot about it last time I was playing with mongo so I created this warning myself. Now this is just a warning and it still works fine, but I don't like to have any weirdness going in my environments so I investigated and i'm glad I did. If not I wouldn't have figured out you can view mongo collections in the browser visually :). To do so just point your browser to:
http://localhost:28017/<dbname>/<collection_name>/ The better way to configure this is with the mongodb.conf file. This bit can bit tricky.
HTTP / Rest interface.

What is a document:

A document is pretty much the same as a JSON object.
This is an empty document { }. Mongo calls this type of JSON a BSON document. Mongo has coined the term BSON to reference the way mongo stores its data. They say to think of as an amalgamation of Binary and JSON. Essentially you can think of BSON as JSON with some super powers. It has some extra abilities like some date stuff and such that normal JSON doesnt have. Enough acronyms though. Let's move on.

Querying Documents in Mongo

In mongo you make a query like so:
db.collectionname.find(<criteria>, <projection>) Where criteria is a query document and projection is a filter of only what you want to get back. If you pass a empty query document or none at all then mongo effectively does a sql * like query returning everything. So db.accounts.find({}) in our case would return everything.

So if we were to look me up by my twitter handle the query would go something like:

db.accounts.find({ twitter_username: "peb7268" })  

and if we were to add a projection to filter the results and only show the twitter username, it would look something like this:

db.accounts.find({ twitter_username: "peb7268" }, { twitter_username: 1, _id: 0 })  

The one signifies inclusion and the 0 exclusion. The reason we had to exclude _id is because it is automatically included on all query result sets.

If you think projections is a weird name for filters you aren't alone. I thought the same thing.

Think of projections as that new age technique of visualizing the reality you want. You think, im going to be successful, buff, and have all the chicks, and its supposed to manifest like that. Thats how a Mongo filter works. You project what kind of document you want and poof. It appears like that.

You can read more on advanced MongoDB queries here and here.

Limiting your result set using Projections.

In mongo you can limit the result set like this:

//db.collection.find(<criteria>, <projection>)
db.accounts.find({ name: { first: "Paul", last: "Barrick"  }}, {name: 1, _id: 0 })  

So in the query above, name was the criteria and name and _id were projection fields. Mongo docs say:

A Projection is a document with a list of fields for inclusion and exclusion.

Projections can be as simple as above where 1 indicates a field to include and 0 indicates a field to exclude or more complicated in which case projection operators are used.

Let's look at a more complex example that uses a query operator and a projection to return a filtered result set:

 db.accounts.find({ twitter_username: { $in: ['peb7268', 'abcUser', 'TomJones'] } }, { twitter_username: 1, name: 1, _id: 0 })

{ "twitter_username" : "peb7268", "name" : { "first" : "Paul", "last" : "Barrick" } }

Querying Subdocuments & Projecting onto them.

I gotta admit. This one stumpped me for a bit. Let's imagine we have the following document:

{ "_id" : ObjectId("5353007df893a6484c000001"), "email" : "peb7268@superawesomeemail.com", "password" : "13d249f2cb4127b40cfa757866850278793f814ded3c587fe5889e889a7a9f6c", "name" : { "first" : "Paul", "last" : "Barrick" } }

The subdocument part would be name. Its a document within a document. One might think that you could query with just the first name to find this record like so:

db.accounts.find({ 'name': {'first': "Paul" } })
or even this perhaps:
db.accounts.find({ 'name': {'first': { "Paul" } } })

But alas, none of those work. You may query a subdocument one of two ways:

  • specify the whole document as the query
  • use dot notation.

The first way is like this:
db.accounts.find({ 'name': { first: "Paul", last: "Barrick" } })
and the second (and my preferable way ) is like this:
db.accounts.find({ 'name.first': "Paul" })

When doing an exact match query on a subdocument ( method 1 ) Your query document must match EXACTLY. The fields even have to be in the same order.