The Top 4 Reasons Why You Should Use MongoDB
Rate this article
Welcome (or welcome back!) to the SQL to MongoDB series. In the first post in this series, I mapped terms and concepts from SQL to MongoDB.
I also introduced you to Ron. Let's take a moment and return to Ron. Ron is pretty set in his ways. For example, he loves his typewriter. It doesn't matter that computers are a bajillion times more powerful than typewriters. Until someone convinces him otherwise, he's sticking with his typewriter.
Maybe you don't have a love for typewriters. But perhaps you have a love for SQL databases. You've been using them for years, you've learned how to make them work well enough for you, and you know that learning MongoDB will require you to change your mindset. Is it really worth the effort?
Yes!
In this post, we'll examine the top four reasons why you should use MongoDB:
You can scale cheaper with MongoDB. Why?
Let's begin by talking about scaling SQL databases. Typically, SQL databases scale vertically-when a database becomes too big for its server, it is migrated to a larger server.
A few key problems arise with vertical scaling:
- Large servers tend to be more expensive than two smaller servers with the same total capacity.
- Large servers may not be available due to cost limitations, cloud provider limitations, or technology limitations (a server the size you need may not exist).
- Migrating to a larger server may require application downtime.
When you use MongoDB, you have the flexibility to scale horizontally through sharding. Sharding is a method for distributing data across multiple servers. When your database exceeds the capacity of its current server, you can begin sharding and split it over two servers. As your database continues to grow, you can continue to add more servers. The advantage is that these new servers don't need to be big, expensive machines-they can be cheaper, commodity hardware. Plus, no downtime is required.
Your queries will typically be faster with MongoDB. Let's examine why.
Even in our simple example in the previous post where we modeled Leslie's data in SQL, we saw that her information was spread across three tables. Whenever we want to query for Leslie's information, we'll need to join three tables together.
In these three small tables, the join will be very fast. However, as the tables grow and our queries become more complex, joining tables together becomes very expensive.
Recall our rule of thumb when modeling data in MongoDB: data that is accessed together should be stored together. When you follow this rule of thumb, most queries will not require you to join any data together.
Continuing with our earlier example, if we want to retrieve Leslie's information from MongoDB, we can simply query for a single document in the
Users
collection. As a result, our query will be very fast.As our documents and collections grow larger, we don't have to worry about our queries slowing down as long as we are using indexes and continue following our rule of thumb: data that is accessed together should be stored together.
Requirements change. Sometimes the changes are simple and require only a
few tweaks to the user interface. But sometimes changes go all the way
down to the database.
In the previous post in this series, we discovered—after implementing
our application—that we needed to store information about Lauren's school.
Let's take a look at this example a little more closely.
To add a new
school
column in our SQL database, we're going to have to
alter the Users
table. Executing the Alter Table
command could take
a couple of hours depending on how much data is in the table. The
performance of our application could be decreased while the table is
being altered, and we may need to schedule downtime for our application.Now let's examine how we can do something similar in MongoDB. When our
requirements change and we need to begin storing the name of a user's
school in a
User
document, we can simply begin doing so. We can choose
if and when to update existing documents in the collection.If we had implemented schema validation, we would have the option of
applying the validation to all inserts and updates or only to inserts
and updates to documents that already meet the schema requirements. We
would also have the choice of throwing an error or a warning if a
validation rule is violated.
With MongoDB, you can easily change the shape of your data as your app
evolves.
To be honest with you, this advantage is one of the biggest surprises to
me. I figured that it didn't matter what you used as your backend
database—the code that interacts with it would be basically the same. I
was wrong.
MongoDB documents map to data structures in most popular programming languages. This sounds like such a simple thing, but it makes a humongous difference when you're writing code.
A friend encouraged me to test this out, so I did. I implemented the code to retrieve and update user profile information. My code has some simplifications in it to enable me to focus on the interactions with the database rather than the user interface. I also limited the user profile information to just contact information and hobbies.
I wrote the code in Python, but, don't worry if you're not familiar with Python, I'll walk you through it step by step. The concepts will be applicable no matter what your programming language of choice is.
Let's begin with the typical top-of-the-file stuff. We'll import what we need, connect to the database, and declare our variables. I'm going to simplify things by hardcoding the User ID of the user whose profile we will be retrieving rather than pulling it dynamically from the frontend code.
MySQL
1 import mysql.connector 2 3 # CONNECT TO THE DB 4 mydb = mysql.connector.connect( 5 host="localhost", 6 user="root", 7 passwd="rootroot", 8 database="CityHall" 9 ) 10 mycursor = mydb.cursor(dictionary=True) 11 12 # THE ID OF THE USER WHOSE PROFILE WE WILL BE RETRIEVING AND UPDATING 13 userId = 1
We'll pass the dictionary=True option when we create the cursor so that each row will be returned as a dictionary.
MongoDB
1 import pymongo 2 from pymongo import MongoClient 3 4 # CONNECT TO THE DB 5 client = MongoClient() 6 client = pymongo.MongoClient("mongodb+srv://root:rootroot@mycluster.mongodb.net/test?retryWrites=true&w=majority") 7 db = client.CityHall 8 9 # THE ID OF THE USER WHOSE PROFILE WE WILL BE RETRIEVING AND UPDATING 10 userId = 1
So far, the code is pretty much the same.
Now that we have our database connections ready, let's use them to retrieve our user profile information. We'll store the profile information in a Python Dictionary. Dictionaries are a common data structure in Python and provide an easy way to work with your data.
Let's begin by implementing the code for MySQL.
Since the user profile information is spread across the
Users
table and the Hobbies
table, we'll need to join them in our query. We can use prepared statements to ensure our data stays safe.MySQL
1 sql = "SELECT * FROM Users LEFT JOIN Hobbies ON Users.ID = Hobbies.user_id WHERE Users.id=%s" 2 values = (userId,) 3 my cursor.execute(sql, values) 4 user = mycursor.fetchone()
When we execute the query, a result is returned for every user/hobby combination. When we call
fetchone()
, we get a dictionary like the following:1 {u'city': u'Pawnee', u'first_name': u'Leslie', u'last_name': u'Yepp', u'user_id': 1, u'school': None, u'longitude': -86.5366, u'cell': u'8125552344', u'latitude': 39.1703, u'hobby': u'scrapbooking', u'ID': 10}
Because we joined the
Users
and the Hobbies
tables, we have a result for each hobby this user has. To retrieve all of the hobbies, we need to iterate the cursor. We'll append each hobby to a new hobbies
array and then add the hobbies
array to our user
dictionary.MySQL
1 hobbies = [] 2 if (user["hobby"]): 3 hobbies.append(user["hobby"]) 4 del user["hobby"] 5 del user["ID"] 6 for result in mycursor: 7 hobbies.append(result["hobby"]) 8 user["hobbies"] = hobbies
Now let's implement that same functionality for MongoDB.
Since we stored all of the user profile information in the
User
document, we don't need to do any joins. We can simply retrieve a single document in our collection.Here is where the big advantage that MongoDB documents map to data structures in most popular programming languages comes in. I don't have to do any work to get my data into an easy-to-work-with Python Dictionary. MongoDB gives me all of the results in a Python Dictionary automatically.
MongoDB
1 user = db['Users'].find_one({"_id": userId})
And that's it—we're done. What took us 12 lines for MySQL, we were able to implement in 1 line for MongoDB.
Our
user
dictionaries are now pretty similar in both pieces of code.MySQL
1 { 2 'city': 'Pawnee', 3 'first_name': 'Leslie', 4 'last_name': 'Yepp', 5 'school': None, 6 'cell': '8125552344', 7 'latitude': 39.1703, 8 'longitude': -86.5366,3 9 'hobbies': ['scrapbooking', 'eating waffles', 'working'], 10 'user_id': 1 11 }
MongoDB
1 { 2 'city': 'Pawnee', 3 'first_name': 'Leslie', 4 'last_name': 'Yepp', 5 'cell': '8125552344', 6 'location': [-86.536632, 39.170344], 7 'hobbies': ['scrapbooking', 'eating waffles', 'working'], 8 '_id': 1 9 }
Now that we have retrieved the user's profile information, we'd likely send that information up the stack to the frontend UI code.
When Leslie views her profile information in our application, she may discover she needs to update her profile information. The frontend UI code would send that updated information in a Python dictionary to the Python files we've been writing.
To simulate Leslie updating her profile information, we'll manually update the Python dictionary ourselves for both MySQL and MongoDB.
MySQL
1 user.update( { 2 "city": "Washington, DC", 3 "latitude": 38.897760, 4 "longitude": -77.036809, 5 "hobbies": ["scrapbooking", "eating waffles", "signing bills"] 6 } )
MongoDB
1 user.update( { 2 "city": "Washington, DC", 3 "location": [-77.036809, 38.897760], 4 "hobbies": ["scrapbooking", "eating waffles", "signing bills"] 5 } )
Now that our
user
dictionary is updated, let's push the updated information to our databases.Let's begin with MySQL. First, we need to update the information that is stored in the
Users
table.MySQL
1 sql = "UPDATE Users SET first_name=%s, last_name=%s, cell=%s, city=%s, latitude=%s, longitude=%s, school=%s WHERE (ID=%s)" 2 values = (user["first_name"], user["last_name"], user["cell"], user["city"], user["latitude"], user["longitude"], user["school"], userId) 3 mycursor.execute(sql, values) 4 mydb.commit()
Second, we need to update our hobbies. For simplicity, we'll delete any existing hobbies in the
Hobbies
table for this user and then we'll insert the new hobbies into the Hobbies
table.MySQL
1 sql = "DELETE FROM Hobbies WHERE user_id=%s" 2 values = (userId,) 3 mycursor.execute(sql, values) 4 mydb.commit() 5 6 if(len(user["hobbies"]) > 0): 7 sql = "INSERT INTO Hobbies (user_id, hobby) VALUES (%s, %s)" 8 values = [] 9 for hobby in user["hobbies"]: 10 values.append((userId, hobby)) 11 mycursor.executemany(sql,values) 12 mydb.commit()
Now let's update the user profile information in MongoDB. Since the user's profile information is stored in a single document, we only have to do a single update. Once again we will benefit from MongoDB documents mapping to data structures in most popular programming languages. We can send our
user
Python dictionary when we call update_one()
, which significantly simplifies our code.MongoDB
1 result = db['Users'].update_one({"_id": userId}, {"$set": user})
What took us 15 lines for MySQL, we were able to implement in 1 line for
MongoDB.
In this example, we wrote 27 lines of code to interact with our data in
MySQL and 2 lines of code to interact with our data in MongoDB. While
fewer lines of code is not always indicative of better code, in this
case, we can probably agree that fewer lines of code will likely lead to
easier maintenance and fewer bugs.
The examples above were relatively simple with small queries. Imagine
how much bigger the difference would be for larger, more complex
queries.
MongoDB documents mapping to data structures in most popular programming
languages can be a huge advantage in terms of time to write, debug, and
maintain code.
The code above was written in Python and leveraged the Python MongoDB
Driver. For a complete list of all of the programming languages that
have MongoDB drivers, visit the MongoDB Manual.
In this post, we discussed the top four reasons why you should use
MongoDB:
Be on the lookout for the final post in this series where I'll discuss
the top three things you need to know as you move from SQL to MongoDB.