I've just arrived to Node.js and see that there are many libs to use with the MongoDB, the most popular seem to be these two: (mongoose and mongodb). Can I get pros and cons of those extensions? Are there better alternatives to these two?
Edit: Found a new library that seems also interesting node-mongolian and is "Mongolian DeadBeef is an awesome Mongo DB node.js driver that attempts to closely approximate the mongodb shell." (readme.md)
https://github.com/marcello3d/node-mongolian
This is just to add more resources to new people that view this, so basically Mongolian its like an ODM...
Mongoose is higher level and uses the MongoDB driver (it's a dependency, check the package.json), so you'll be using that either way given those options. The question you should be asking yourself is, "Do I want to use the raw driver, or do I need an object-document modeling tool?" If you're looking for an object modeling (ODM, a counterpart to ORMs from the SQL world) tool to skip some lower level work, you want Mongoose.
If you want a driver, because you intend to break a lot of rules that an ODM might enforce, go with MongoDB. If you want a fast driver, and can live with some missing features, give Mongolian DeadBeef a try: https://github.com/marcello3d/node-mongolian
Mongoose is, by far, the most popular. I use it, and have not used others. So I can't speak about the others, but I can tell you my gripes with Mongoose.
Difficult / poor documentation
Models are used. And they define structure for your documents. Yet this seems odd for Mongo where one of its advantages is that you can throw in a column (err, attribute?) or simply not add one.
Models are case sensitive - Myself and other devs I work with have had issues where the case of the collection name that the model is defined with can cause it to not save anything, w/o error. We have found that using all lowercase names works best. E.g. instead of doing something like mongooseInstace.model('MyCollection', { "_id": Number, "xyz": String }) it's better to do (even though the collection name is really MyCollection): mongooseInstace.model('mycollection', { "_id": Number, "xyz": String })
But honestly, it's really useful. The biggest issue is the documentation. It's there, but it's dry and hard to find what you need. It could use better explanations and more examples. But once you get past these things it works really really well.
I'm building new app and designing now structure of it, here are some thoughts about why to use or not to use mongoose:
Mongoose will be slower (for big apps) Mongoose is harder with more complicated queries There will be situations when you want more speed and you will choose to go without mongoose then you will have half queries with mongoose and half w/o. That's crazy situation, had once.. Mongoose will make you code faster with simple apps with simple db structure Mongoose will make you read mongodb docs AND mongoose docs With mongoose your stack will get one more thing to depend on and it's one more possibility to crash and burn to ashes.
mongodb driver is raw driver, you communicate directly to mongodb. mongoose is abstraction layer. You get easier I/O to db while your db structure is simple enough.
Abstraction brings in it's requirements and you have to follow those. Your app will be slower, eat more RAM and be more complicated, but if you know how to use it, you can faster write simple objects, save those to database.
Without mongoose you will have faster application with direct connection to mongodb. No-one says, that you can't write your own models to save stuff to db. You can. And I think it's easier. You write code, which you will use, you know what you need. You abstraction layer will be way smaller, then mongoose's.
I'm coming from PHP world, there we had raw sql with depreciated mysql_ functions, then we got PDO - object orientated abstraction layer to communicate with sql. Or you can choose some heavy ORM like Doctrine to have similar stuff to mongoose on mongoDB. Objects with setter/getters/save method and so on. That's fine, but by adding more abstraction you are adding more files, more logic, more documentation, more dependencies. I like to keep stuff simple and have less dependencies in my stack. BTW, that was why I moved from PHP to server-client Javascript in first place..
With mongoose I think is great to write some simple apps, that have simple db structure similar to sql. When you start having subdocuments and want to make all those crazy queries i found it really hard with mongoose. You have to look at mongodb docs, then look at mongoose docs to find out how to make a query you want. Sometimes you will find, that X future of mongodb is not in mongoose, so you go down to raw mongodb driver and write raw mongodb queries in one or another place. Without mongoose, you look at mongodb docs and do your query.
I have only used mongodb. In my personal opinion, I would recommend starting of with something low level and then moving up. Otherwise you may find yourself using the additional advanced features provided by higher level drivers like mongoose to no actual benefit.
The problem I have had with mongodb, which is endemic to node.js is the poor documentation. There is documentation and a lot of it but it isn't always the most helpful. That I have seen so far there are no good and thorough examples of production usage of the driver. The documentation is filled with the same templated example of open a connection, issue a command and close the connection. You can tell it's copy and pasted from a template because every example includes required for everything that might be needed rather than only what is needed for each example.
To give an example taken entirely at random:
raw {Boolean, default:false}, perform operations using raw bson buffers.
What exactly does "perform operations using raw bson buffers" do? I can't find it explained anywhere and a Google search for that phrase doesn't help. Perhaps I could Google further but I shouldn't have to. The information should be there. Are there any performance, stability, integrity, compatibility, portability or functionally advantages for enabling/disabling this option? I really have no idea without diving deeply into the code and if you're in my boat that's a serious problem. I have a daemon where perfect persistence isn't required but the program needs to be very stable at runtime. I could assume this means that it expects me to deserialize and serialize to JSON or is something low level, internal and transparent to the user but I could be wrong. Although I tend to make good assumptions I cant rely on assumption and guesswork when making vital systems. So here I can either test my assertion with code or dig much deeper into Google or their code. As a one off this isn't so bad but I find my self in this situation many times when reading their documentation. The difference can mean days spent on a task versus hours. I need confirmation and the documentation barely gives me explanation, let alone confirmation.
The documentation is rushed. It doesn't explain events, gives vague details about when errors are thrown or the nature of those errors and there are often several ways to accomplish connectivity which can be unclear. You can get by and its not completely useless, but it is very rough around the edges. You'll find some things are left to guesswork and experimentation.
Success story sharing