I signed up for the online MongoDB University MongoDB for Node.js Developers course aka M101JS. MongoDB sounds like a promising technology and MongoDB’s courseware uses EdX’s excellent software that I had already used for the MIT 6.002x Electronics course so I was pretty confident of the usefulness of all this.

Work in Progress! I switched from Python to Node.js and started over. I'm currently in:
  • Week 5, “Compound Grouping”.
  • Week 6, next video is “Connecting to a Replica Set from the Node.js driver”
  • Week 7, next video is “Introduction to Blog”

Introduction to MongoDB

MongoDB is a non relational datastore. It stores something close from JSON called BSON, which stands for Binary JSON. It is schemaless.

The trade-off to gain scalability and performance is that you have to give up joins and transactions that relational databases provide.

CRUD

In MongoDB vocabulary:

  • Create is insert
  • Read is find (analogous to count)
  • Update is update
  • Delete is remove

Table is collection. _id is created by default.

Mongo Shell

MongoShell is basically a JavaScript interpreter. You’ll be able to CRUD data but also run simple JavaScript instructions.

Features include:

  • Autocompletion via the TAB key
  • Support of . and [] notation for JavaScript objects
  • Support of BSON datatypes

Connextion to the shell: mongo

Example:

> show dbs
> use mydb

> for (i = 0; i < 3; i++) print("Hello World");
Hello World
Hello World
Hello World

> help

> obj = { "a" : 1, "b": "hello", "c": ["apple", "tomatoes"]}

> NumberInt(1)

> NumberLong(1)

> new Date()

> exit

Query Language

_id is returned by default with queries. pretty() helps formatting answers in a readable way. The second argument tells MongoDB the name of the fields we want to fetch.

> db.collection.findOne()
> db.collection.findOne({"name": "Jones"})
> db.collection.findOne({"name": "Jones"}, {"name": true, "_id": false})
> db.scores.find( { type: "essay", score: 50 }, { student: true, _id: false } );

Query operators

  • { $gt : 95 }: greather than (>, NOT >=)
  • $gte, $lt, $lte are >=, < and <=
  • $exists: true/false filter documents where the specified field exists or not
  • $type (example: 2 for String, cf. BSON specifications)
  • $regex (example: “^A$”)

Example:

> db.scores.find( { type: { $exists: true } } );

Prefix Query operators

  • $or + array
  • $and + array (not as useful)

Tricky : db.scores.find( { score : { $gt : 50 }, score : { $lt : 60 } } ); # only less than 60 are returned. Beware that $and is not used, but the 2nd score field value is replacing the 1st score field value (this is kind of a normal dictionary behavior).

Querying inside arrays

  • Polymorphism
  • $all : [ elem1, elem2 ]
  • $in : [ enum1, enum2 ]

Cursor Operations

Processed on the server-side:

  • sort
  • limit
  • skip

Update options

  • set, unset
  • push, pop, pull, pushAll, pullAll, addToSet
  • upsert, multi

Error feedback

db.runCommand( { getLastError: 1 } )

Dot notation

Don’t forget the double-quotes!

Performance

Basic Usage of Indexes

Creating an index

db.collection.ensureIndex( { my_key: 1 }, opts ) # 1 is ascending, -1 is descinding

opts can be:

  • missing
  • { unique: true }
  • { unique: true, dropDups: true } (RISKY!)
  • { sparse: true } (RISKY!)

Indexes can be created in the background.

Finding existing indexex

db.system.indexes.find()

or

db.collection.getIndexes()

Dropping an index

db.collection.dropIndex( { my_key: 1 } )

Fine Tuning

Explain

Adding .explain() on a query produces a document explaining how the request was executed. Some of the most relevant information of this document are:

  • cursor: it tells you if an index was used (BtreeCursor) or not (BasicCursor)
  • millis: it tells you how long the request took in milliseconds
  • indexOnly: it tells you if the index was enough to return the result of the request

Size of an index

Calling .stats() on a collection gives you a document with some interesting information. One particularly important information is the size of your index (you want your index to fit inside the memory) that you can also get directly via .totalIndexSize().

Profiling

http://docs.mongodb.org/manual/reference/method/db.setProfilingLevel/

db.system.profile.find({millis: { $gt: 1000 }}).sort({ts: -1})

http://docs.mongodb.org/manual/reference/program/mongotop/