28
Transitioning from MySQL to MongoDB
When going into software development, for most web applications, there is a need to store data, persistently, in some form or the other. This could include the need to store login/authentication information, financial details, an e-shopper's cart, training data for a machine learning model, etc. Amazingly, there are myriads of ways to store this data, examples include JSON (JavaScript Object Notation), XML, CSV (comma-separated values), or in a database, the most popular option, of course, being the most popular of them all.
This article will not discuss the different types of database systems, like RDBMS and so on. We will, however, focus on two concepts: SQL Databases and NoSQL databases.
SQL (Structured Query Language) is a standardized programming language that's used to manage relational databases and perform various operations on the data in them. Read More.
The data in relational databases is stored in rows and columns which are arranged in relevant tables and stored in the overall database.
According to the MongoDB Webpage, NoSQL databases (aka "not only SQL") are non-tabular databases and store data differently than relational tables. NoSQL databases come in a variety of types based on their data model. The main types are document, key-value, wide-column, and graph. They provide flexible schemas and scale easily with large amounts of data and high user loads.
The NoSQL database of choice we would be looking at today is MongoDB.
MongoDB is the most popular solution for developers looking to benefit from features like scalability and speed. Unlike MySQL, MongoDB returns data as a well-organized, JSON document with helper methods that help to execute more complex queries on the data.
In place of tables, MongoDB uses a Schema, which defines the datatypes, constraints, and other parameters to construct Models that represent tables and are the ways we access, create and modify data. These models are then used to organize data into collections.
If you're used to viewing data in a graphical form such as PHPMyAdmin for MySQL, MongoDB also has the MongoDB Compass, to provide such capability.
To go through this article, we'll use the Mongoose npm package.
The file structure for this project will look something like this.
----/
|
|--app.js
|--package.json
|--models
|--User.js
Run the following commands in this folder.
> npm init -y
> npm install mongoose nodemon
Inside package.json, under scripts, include the following
...
"start": "nodemon app.js"
...
Inside User.js
, we'll create a Mongoose Model with the following lines of code
const mongoose = require('mongoose');
const {Schema} = mongoose;
const userSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
name: {
type: String,
required: true
}
});
module.exports = mongoose.model('User', userSchema);
The SQL equivalent of this would look something like this
CREATE DATABASE `transition-tutorial`;
USE `transition-tutorial`;
CREATE TABLE `users` (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
username VARCHAR(20) NOT NULL UNIQUE,
password VARCHAR(20) NOT NULL
);
Here we can see how we use Schema to define the data structure and parameters, and then process it into, and export a Model object. Additionally, notice how we didn't define an id
property in our Schema. That's because MongoDB automatically assigns a 16-bit unique ObjectId to all documents in the model. Amazing.
Inside app.js
, write the following lines of code
const mongoose = require('mongoose');
const User = require('./models/User');
(async () => {
try {
await mongoose.connect(
'mongodb://127.0.0.1:27017/transition-tutorial',
options);
} catch (err) {
console.log('Error connectiong to Database');
console.log(err);
}
});
And here, we include the constructed model object into our file.
Two things to note
We see from the connection that Mongoose is designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.
The string
'mongodb://127.0.0.1:27017'
represents the connection URL for the mongoose instance. The URL in this tutorial is for those who have the MongoDB application installed on their local computer. Connecting to a cloud instance requires a connection string gotten from your MongoDB Cloud cluster homepage.The
'transition-tutorial'
is the name of the database we will be querying. We did not create this database because MongoDB automatically creates it along with any defined Model when we connect and insert our first document using that Model Object. Another amazing reason to switch to MongoDB.
Now, run npm start
in the terminal.
Typically, in an SQL database, the way to insert data into a table would be
INSERT INTO `users` (name,username,password) VALUES ('John', 'johnsmith', 'p@$$w0rd!');
The MongoDB equivalent of this would be
...
(async () => {
try {
const user = new User({name: 'John', username: 'johnsmith', password: 'p@$$w0rd!'});
await user.save();
console.log(user);
} catch (err) {
console.log(err);
}
})();
If you take a look at the output in the terminal or console, you'll notice that the new User Object has an _id
property. This is the unique id that was generated by Mongoose;
To retrieve data from a SQL database, for example users, you'd usually write a query like this
SELECT * FROM users
This corresponds to following line of code
(async () => {
const users = await User.find({});
console.log(users);
});
This returns an array of MongoDB documents.
To perform a WHERE query, simply add the conditions as properties in the find
method.
const users = await User.find({name: 'John'});
This retrieves all users who have the name John while
To only retrieve some properties, supply a comma-separated string as the second parameter.
const users = await User.find({}, 'name, username');
This will return only the name
and username
properties, as well as the unique _id
. The SQL equivalent of this would look like
SELECT name, username FROM users;
This would find and return records based on the unique ID, provided you already have the id
const user = await User.findById(id);
console.log(user);
To return one document using one of the properties, for example, the name, write this
const user = await User.findOne({name: 'John'});
This returns the first user in the collection with the name John.
The SQL equivalent of this would look like
SELECT * FROM users WHERE name='John';
To update a record in a SQL database, we use the UPDATE query
UPDATE TABLE users SET password='johnsmith001' WHERE name='John';
To achieve this in MongoDB, we could go two ways
-
First, we could retrieve the data from the database, update the document and then save it again.
const user = await User.find({name: 'John'}); user.password = 'johnsmith001'; await user.save();
-
Secondly, we could
findAndUpdate
,findOneAndUpdate
orupdateOne
and the documents directly.
// Update multiple documents const user = await User.findAndUpdate( {}, {password: 'johnsmith001'}, {new: true} ); // Update multiple documents with condition const user = await User.findAndUpdate( {name: 'John'}, {password: 'johnsmith001'}, {new: true} ); // Update single document const user = await User.findOneAndUpdate( {name: 'John'}, {password: 'johnsmith001'}, {new: true} ); // Update single document const user = await User.updateOne( {name: 'John'}, {password: 'johnsmith001'}, );
The first parameter to pass is an object of the conditions used to locate the required document, the second parameter is an object of the updates to be made to the document, and the
{new: true}
tells mongoose to return the updated record. If this is not included, the old, outdated document will be returned instead.
To delete records in a SQL database, the typical query would look like this.
DELETE FROM users WHERE name='John';
The equivalent mongoose function would resemble any one of the following ways
// Deleting collection of documents
const users = await User.deleteMany({name: 'John'});
const users = await User.remove({name: 'John'});
// returns {deletedCount: x} where x is the number of documents deleted.
// Deleting Single Document
const user = User.findOneAndDelete({name: 'John'});
console.log(user); // returns the deleted document
Note:
- The
deleteMany
method is preferred over theremove
unless you have a good reason otherwise.
We've taken a look at the common operations that can be performed by querying a SQL database and the ways they can be implemented in MongoDB using mongoose. Don't stop there. There are many other things we could discuss such as implementing the LIKE query by passing a regex as the find condition and implementing JOIN queries with the populate
method.
Create a MongoDB account for free today and take advantage of all the features MongoDB has to offer.
28