Marcus Node Bits: monk is an easy way to access MongoDb

Posted by Marcus Hammarberg on February 7, 2014
Stats
I'm writing down some of the things I've picked up when I started to learn about NodeExpress and Mongo. Here are all the post in the series:
This post is about monk, a nice framework that makes accessing MongoDb really easy.

I'm writing down some of the things I've picked up when I started to learn about NodeExpress and Mongo. Here are all the post in the series:
This post is about monk, a nice framework that makes accessing MongoDb really easy.

When doing database work with Node, the default option seems to be MongoDb. This is of course very natural since Mongo itself is Javascript and stores JSON objects. I have no problem at all with that, since I've used Mongo before and like it a lot.

When accessing Mongo from Node, the default option seems to be Mongoose. It seems like a very nice and capable framework, but it enforces a typed model to be declared, before you can use Mongoose in your code. I have some problems with that.
Firstly it seems to go against the Node/Javascript concepts where not much is statically typed. Secondly, in Mongo there is no types and you can store whatever you want in a collection (kinda table for relational people). Thirdly, I have been using Simple.Data for so long that the idea of having to create a model just to be able to get some data out of a database seems unnecessary complex to me.
Then again... using the native Mongo driver for node, doesn't look to attractive to me. But I rather do that then using a model... So I was between a rock and a hard place.

I then found out about MongoSkin (you guys and your framework names...), that looked much more attractive. MongoSkin is built directly on top of the native Mongo driver but takes away much of the complexity and gives you a nicer API to program against, in my opinion.
Using MongoSkin led me to Monk and I felt back at home. Monk has a nice, slick API that gets out of my way and lets me just do the work. Not a declared model as far as the eye can see.  Monk is built on top of MongoSkin, which in turn is built on top of the native Mongo driver... So it all goes together.

The API

If there's something to be said against Monk it is that the documentations is not that easy to digest. But since it's just a wrapper of MongoSkin you can sometimes fall back to the MongoSkin documentation and it just works. And if that is failing... MongoSkin is a wrapper and you can go to the Mongo Driver Native wrapper. We'll see that in play shortly. In fact, some people who know the native driver or MongoSkin might object and say that the features I describe actually belongs to MongoSkin or the native driver. I really don't care, I just like the Monk-syntax. 

Let's see Monk in action (hey that's a cool book title) in some mocha tests.

Connecting

Setting up a connection is trivial and can be done with this simple line

This gives you a database of which you can access the other properties you need. Like the collections for example, like we do in the other test. Quite often it's a good idea to actually get a reference to a collection while you're at it.
All the interesting work is done from the collection object, so I often create this in my initialization code. For tests, that would be in a beforeEach-function: 

Add stuff in

Yes, I'm writing stuff in the title. Should have been documents I guess. But often, the thing that we're adding is not that visible in our code. Its just a data structure and we don't really need to care how it looks like. Since we're just adding (deleting or getting) them from the database. That's why I have a problem with a model being enforced upon me. The concept in Mongo is schemaless and hence a model feels contrived. 

Oh yes, adding stuff. Here are some simple ways of inserting data:

Update stuff already in there

Updating is rather easy, the update function first takes a query parameter, that tells what to update, and then the instruction on how to update. It looks funky but is really powerful since that means that it's easy to write updates for many documents at once:

Delete stuff

Deleting documents is really simple and just takes a query that tells us what to remove
You can also drop collections all together, like in the after-function at the end:

Find stuff that's in there

Querying data is the most powerful and hence complex features. I've put together some tests that shows off the capabilities that I've come to use and like:
That options structure, at the end of the tests, is a story of its own then it was the options-structure. This is a VERY powerful feature that confused me for a long time. There's an parameter to the find-methods (that trickles down all the way to the native mongo driver) that configures your query. With this you can limit the number of results, sort the result, have it explain the query for you and you can probably ask it to make coffee too. The complete description of all the options can be found here.
Here are options I've used so far:
  • limit {Number, default:0} - sets the limit of documents returned in the query.
  • sort {Array | Object} - set to sort the documents coming back from the query. Array of fields and the asc/desc property, like this [[‘field name’, 'desc']].
  • skip {Number, default:0} - set to skip N documents ahead in your query. Together with limit this makes for quite easy handling of pagination
Once you get over the initial fear of having all those JSON-object literals being passed into the function (that at least scared me at first) it's a very nice terse syntax.

RoboMongo

Almost forgot... To view and handle Mongo databases my tool of choice is RoboMongo. Go get it now. It's free. It's awesome. 


Published by Marcus Hammarberg on Last updated