Getting to know MongoDB
When we started studying MongoDB, our developers wrote a short guide for colleagues to describe the main Mongo functions. Having found this article in our corporate blog recently, we decided to share it with public. We hope our guide is useful for newbies.
MongoDB is a cross-platform, document-oriented database. It’s classified as one of the most popular NoSQL database solutions. MongoDB provides horizontal scalability as part of its core functionality and, as would be expected, it has its own advantages and disadvantages.
The MongoDB scheme significantly differs from more usual scheme of SQL databases, for example, MySQL. Mongo databases consist of collections. Collections consist of documents, and documents contain fields and their values. A collection may be considered a table of a relational database except there are no aligned columns.
Even if the scheme seems a bit unusual at first sight, it’s quite easy to understand how everything works.
So, let’s talk about the main operations in MongoDB. As a sample database, we use a few countries along with their capitals, population, and cities.
Read operations: search and sort
We can run the following query to select all documents from a single collection:
db.countries.find();
This is the sample of how the query looks in the Mongo shell interface. You can notice the similarity with JavaScript objects. Besides, the shell interface itself is in JavaScript.
This is how the same query looks in PHP:
$db -> countries -> find();
In the following examples, we give both versions of the query, for shell and for PHP.
The query mentioned above returns the list of documents. Each of them is a JSON-object:
{
_id : '549027191cdcaf3594625f4c',
name: 'Ukraine',
capital: 'Kiev',
towns: [
'Kharkiv', 'Kiev', 'Lviv'
],
population: 45
},
{
_id : '549027191cdcaf3594625f3c',
name: 'England',
capital: 'London',
towns: [
'London', 'Liverpool', 'Manchester'
],
population: 53
}
If you need to filter the results by particular criteria in MongoDB, you must specify the query criteria to the find() method (In SQL, we specify them in WHERE clauses):
db.countries.find({name: 'Ukraine'}); (Shell)
$db -> countries -> find(['name' => 'Ukraine']); (PHP)
{
_id : '549027191cdcaf3594625f4c',
name: 'Ukraine',
capital: 'Kiev',
towns: [
'Kharkiv', 'Kiev', 'Lviv'
],
population: 45
}
To select particular fields only, specify the projections that are the second argument to the find() method. In SQL, we use SELECT clauses for this.
db.countries.find({name: 'Ukraine'}, {'capital': 1}); (Shell)
$db -> countries -> find(['name' => 'Ukraine'], ['capital' => 1]); (PHP)
{
_id : '549027191cdcaf3594625f4c',
capital: 'Kiev'
}
In this sample, the query selects documents from the countries collection. The selected documents match the specified criterion: to have “Ukraine” in the name field. The projection specifies that the query should return just the capital field value in the result set.
What if you need to calculate the number of documents returned by the query? Use count() method for this purpose:
db.countries.find({name: 'Ukraine'}, {'capital': 1}).count(); (Shell)
$db -> countries -> find(['name' => 'Ukraine'], ['capital' => 1]) -> count(); (PHP)
The sort() method specifies the order in which the query returns matching documents. This command has a list of options to determine the sort order.
Use values of 1 or -1 to specify an ascending or descending sort, respectively.
db.countries.find().sort({name: 1, capital: -1}); (Shell)
$db -> countries -> find() -> sort(['name' => 1, 'capital' => -1]) (PHP)
The sample query shown above specifies an ascending sort by the name field and then a descending sort by the capital field.
MongoDB has a set of special query selector operators: $lt, $lte, $gt, $gte and $ne. They express the following operations: less than, greater than, less than or equal to, greater than or equal to, and not equal.
db.countries.find({population: {$gt: 50}}); (Shell)
$db -> countries -> find(['population' => ['$gt' => 50]]) (PHP)
This query selects countries that have a population greater than 50 million people.
Another useful operator is $or:
db.countries.find({$or: [{towns: 'Kharkiv'}, {towns: 'London'}]}); (Shell)
$db -> countries -> find(['$or' => [['towns' => 'Kharkiv'], ['towns' => 'London']]]); (PHP)
It’s worth mentioning that towns is an array, but MongoDB will return a document if this array contains at least one town from the query.
Write operations: delete, insert, update
In MongoDB, the remove() method deletes documents from a collection. Similarly to the find() method, it accepts query criteria to determine which documents to remove:
db.countries.remove({capital: 'London'}); (Shell)
$db -> countries -> remove(['capital' => 'London']); (PHP)
Pay attention, if you don’t set any parameters to the remove() method, the query will delete all documents from a collection.
Use the insert() method to add new documents to the collection:
db.countries.insert({name: 'USA', capital: 'Washington', towns: ['New York', 'Washington'], population: 322}); (Shell)
$db -> countries -> insert(['name' => 'USA', 'capital' => 'Washington', towns: ['New York', 'Washington'], 'population' => 322]); (PHP)
If you need to modify existing documents in a collection, use the update() method that slightly differs from UPDATE in SQL. The update() method accepts two arguments. The first one—the update criteria—determines which documents in the collection to modify. The second one—the update action—describes what modifications to apply. One word of caution, though, if the query doesn’t contain the $set modifier, the new document that contains the fields specified in the second parameter will replace the current document.
db.countries.update({name: 'Ukraine'}, {$set: {population: 50}}); (Shell)
$db -> countries -> update(['name' => 'Ukraine'], ['$set' => ['population' => 50]]); (PHP)
This query updates the number of people in Ukraine.
The update() method accepts two more useful arguments: upsert and multi. If the update() method includes upsert: true, and no documents match the query criteria of the update operation, then it creates a new document.
If the update() method includes multi: true, the update operation will modify all documents that meet the query criteria.
db.countries.update({}, {$set: {population: 50}}, false, true); (Shell)
$db -> countries -> update([], ['$set' => ['population' => 50]], ['upsert' => false, 'multi' => true]); (PHP)
The update() method also has the $inc operator that increases the value of the field by the specified amount and the $push operator that adds an item to an array.
db.countries.update({}, {$inc: {population: 2}}, false, true); (Shell)
$db -> countries -> update([], ['$inc' => ['population' => 2]], ['upsert' => false, 'multi' => true]); (PHP)
This query increases the population in all countries by 2 million.
db.countries.update({name: 'Ukraine'}, {$push: {towns: 'Mariupol'}}); (Shell)
$db -> countries -> update(['name' => 'Ukraine'], ['$push' => ['towns' => 'Mariupol']]); (PHP)
This query adds Mariupol to the Ukrainian towns array.
Speaking about other Mongo advantages, this database management system easily surpasses MySQL in performance by insert and selection. Since Mongo provides horizontal scalability, it’s easy to use it for sharding. It also provides replication, indexes, and tools for backup and restoration. However, MongoDB doesn’t have transactions and JOIN-s.
It’s significant to note that MongoDB is a denormalized database. Therefore, if you plan to have many relations in your DB, then using any familiar relational database is a better solution.
Where to use MongoDB?
As a sample of MongoDB usage, we can cite Yandex Disk. It uses Mongo to store metadata. Twelve billion objects were stored on shards (servers) at November 2014. The total data volume was 12 TB (indexes occupied 5 TB). The number of queries per day exceeded 6 billion. However, according to the Yandex Disk developer’s words, they don’t feel very comfortable with this database because they made a mistake in designing architectural solutions while planning.
As we can see, the most important thing is to organize the data structure correctly and apply MongoDB only in those projects where we actually can apply it.
MongoDB itself surely cannot completely substitute well-known relational database management systems, such as MySQL or PostgreSQL. However, developers can use Mongo together with other databases to increase response rate of particular elements in the project architecture. The good solution is to use MongoDB for keeping statistics and system logs, saving user sessions, etc.
For example, we use MongoDB in combination with other technologies in one of our current projects. We apply Mongo to store the history of users’ actions (for example, deleting, adding or changing the information) and to save system changes (for example, the update of objects) in the log. We also use MongoDB to create a social network for this project, in particular to store all necessary data: messages, posts, groups, events, etc.
We haven’t load-tested the project yet. However, we expect the data exchange speed will be much higher than when using MySQL for the same purpose. We use MariaDB as the main database management system in this project. The server-side code is written in PHP, using JavaScript and Node.js.
***
We hope you enjoyed reading our guide and found it useful. If you have any thoughts about MongoDB usage or would like to use it in your project, drop us a line. We’re here to help.