For those who are new to MongoDB, it's a NoSQL-Document database. Documents comprise sets of key-value pairs and are the basic unit of data in MongoDB.
It is definitely one of the most popular NoSQL databases as of now. It's widely accepted and fits a wide variety of use cases (though not all of them).
In this article of the good, the bad, and the ugly, I would like to give a brief overview based on my experience with MongoDB during the past few years.
Since MongoDB is as popular as it is today, there should be more good than the bad and the ugly. If not, developers wouldn't accept it. Below are a few good things about MongoDB.
Flexible Data Model
In today's dynamic use cases and ever-changing applications, having a flexible data model is a boon. A flexible data model means that there is no predefined schema, and the document can hold any set of values based on any key.
Expressive Query Syntax
The query language of MongoDB is very expressive and is easy to understand. Many would say that it's not like SQL. But why should we stick to a SQL-like query language when we can move forward and be more expressive and simple?
Easy to Learn
MongoDB is easy to learn and quick to start with. The basic installation, setup, and execution doesn't take more than a few hours. The more robust setup might be complex, but I will talk about it later.
You should be able to use the MongoDB database with ease in your project.
Query performance is one of the strong points of MongoDB. It stores most of the workable data in RAM. All data is persisted in the hard disk, but during a query, it does not fetch the data from the hard disk. It gets it from the local RAM and, hence, is able to serve much faster. Here, it is important to have the right indexes and enough RAM to benefit from MongoDB's performance.
Scalable and Reliable
MongoDB is highly scalable, using shards. Horizontal scalability is a big plus in most NoSQL databases. MongoDB is no exception.
It is also highly reliable due to its replica sets, and the data is replicated in more nodes asynchronously.
Nonblocking IO using async drivers are essential in all modern applications that are built for speed. MongoDB has async driver support for most of the popular languages.
Having a good documentation can make developers' lives a lot easier, especially when the developer is new to the technology. MongoDB has superb documentation.
If you are building a website that needs to search all of your data, text search is essential. For example, an eCommerce website with a text-search-enabled database can be a lot more lucrative for the users.
If you need some operations to be performed on the server side and not in your application, you can do that in MongoDB. Put your list of mongo statements in a .js file and execute mongo yourFile.js.
Documents = Objects
The good thing about having a document database is that your object can directly be stored as a single document in MongoDB. There is no need of an ORM here.
We looked at the various good things about MongoDB. Below are the few bad things. I am sure the critics are more interested in this part. MongoDB can be evil if we use it in for an improper use case.
Nowadays, there are very few applications that actually require transactions. But some applications still need it. MongoDB, unfortunately, does not support transactions. So if you need to update more than one document or collection per user request, don't use MongoDB. It may lead to corrupted data, as there is no ACID guarantee. Rollbacks have to be handled by your application.
In RDBMSs, we have the luxury of triggers, which have saved us in many cases. This luxury is missing in MongoDB.
MongoDB needs more storage than other popular databases. The introduction of WiredTiger in MongoDB 3.0 has solved the storage issue, but using WiredTiger may not be ideal for most of the applications.
MongoDB does not automatically clean up the disk space. So if the documents are rewritten or deleted, the disk space is not released. This happens during restart or has to be done manually.
Sometimes, the ugly can be worse than the bad. It's important to know the ugly part before using the technology. It does not stop you from using the product, but it can make your life very tough.
Hierarchy of Self
If you have a data model where an object can have recursive children (i.e., same object type is a child of an object and it keeps going for 'n' levels), the MongoDB document can become very ugly. Indexing, searching, and sorting these recursive embedded documents can be very hard.
Joining two documents is also not simple in MongoDB. Though MongoDB 3.2 supports left outer joins (lookup), it is not yet mature. If your applications require pulling data from multiple collections in a single query, it might not be possible. Hence you have to make multiple queries, which might make your code look a bit messy.
Though speed is advertised as a big plus of MongoDB, it is achievable only if you have the right indexes. If you end up having poorly implemented indexes or composite indexes in an incorrect order, MongoDB can be one of the slowest databases.
If you have a lot of filter by and sort by fields, you may end up having a lot of indexes on a collection, which, of course, is not good.
You may end up having a lot of duplicate data, as MongoDB does not support well-defined relationships. Updating this duplicate data can be hard and, also due to lack of ACID compliance, we might end up having corrupted data.
Overall, MongoDB is a good database, provided it suits your use case. If it does not, it can get very ugly. Try using it in the wrong place and you will get burned.
Analyze it well and consult an expert. You will definitely enjoy using it when it's right.
As for the bad and the ugly parts, you can work around a few of them using the design patterns which I have explained in my article MongoDB Design Patterns.
MongoDB Best Practices
A few MongoDB best practices are listed below:
- Ensure your working set fits in RAM.
- Use compression.
- Run a single MongoDB per server.
- Use SSDs for write-heavy applications.
- Store all data for a record in a single document.
- Avoid large documents.
- Avoid unnecessarily long field names.
- Eliminate unnecessary indexes.
- Remove indexes that are prefixes of other indexes.
- Update only modified fields.
- Avoid negation in queries.
- Run explain() for every complex query.
- Use covered queries when possible.
- Use bulk inserts when needed.
Setup and Configuration
- Have at least one secondary and one arbiter.
- Set write concern to 2 when the data is critical.
- Havea daily dump of data for backup.