When to use NoSQL — Getting started with MongoDB in Laravel

Image for post
Image for post
Photo by Manuel Geissinger from Pexels

This post has an audio version thanks to Miguel Piedrafita’s Blogcast app.

In case you have followed me for quite a while, I have published this specific article: Setup MongoDB for Laravel on ploi.io. In case you need to deploy your application to production without “hassle”, ploi.io might seem a great choice. This time, I’ll introduce you to MongoDB on Laravel.

NoSQL (MongoDB) seems quite unpopular on Laravel, not because no one cares, but because not many people are going to use Mongo over SQL since SQL is already embedded into Laravel and provides a great experience for newcomers to understand how Laravel works with databases.

In case you don’t know what are the ups’n’downs of NoSQL over SQL, head back to the previously mentioned article on which not only I’m explaining how to deploy MongoDB on a cloud server instance, but that’s all about running NoSQL with Laravel. This time, I’ll just break through each up’n’down shortly while giving examples and how things work, how to use it locally and how they affect the production environment.

Starting from ground zero — you have to be quite familiar with Laravel Eloquent ORM to adventure yourself further. If you are not quite familiar, it’s always time to learn! Be eager to learn things all the time!

Prerequisites & running it locally

There’s nothing much to do — you just need to have MongoDB running on your machine. I strongly encourage people to run a Valet or Homestead on their local machines because it’s easier. When it comes to MongoDB, I only worked with Homestead. So if you are one of the lucky winners that can work with Homestead, head on your Homestead.yaml file and add mongodb: true to that. This is my pretty-basic configuration for Homestead:

I also encourage you to use the vendor/bin/homestead make command instead of copying the configuration I stated as an example because the path to your folder should be auto-generated by that command. What I stated in this example was the fact that I have a mongodb: true there.

All you have to do further is to re-provision the machine (or run it with --provision in case you never up-ed your machine).

Congrats! You got your MongoDB server running inside the VM. It can be accessed using localhost as host and homestead and secret as user and password in your .env.

Eloquent ORM for NoSQL

Jens Segers’ MongoDB package is pretty popular. It might be more packages that handle NoSQL, but when it’s based on the community — we must trust it more. I have also run it in production for quite a while, and so far, I never encountered problems with it.

The setup is pretty straightforward if you read the documentation — it will help you install it through Composer, set up a database driver. We’ll focus just on the important things.

This package offers a Moloquent model, as the documentation states. It is an Eloquent model but made for Mongo. If you worked with ORM for a while, you would be familiar with this kind of look:

In this case, we will no longer extend from Model, the basic model which Laravel gives us.

SQL works with tables, NoSQL works with collections. Instead of the $table variable, we’ll have a $collection variable. Also, it’s pretty important to note that the primary key cannot be set through $primaryKey and the $incrementing is unavailable. Additionally, you might want to specify that the model belongs to the mongodb connection you have created earlier:

You must be at peace with the fact that MongoDB auto-assign primary keys to documents (the equivalent of rows from SQL). So, to access the primary key of a document, you just have to use the same attribute name as in the basic model:

Using find() uses the primary key field to retrieve the result:

Almost no schemas to define

In NoSQL, we don’t have schemas to define. We can go as crazy as we want. But we can take advantage of the migrations to define indexes, unique fields, and other mongo-specific fields:

The migration process is the same. To be able to run the migrations, make sure that the default driver set (the DB_CONNECTION env variable) is set to mongodb.

In case you wanna run both SQL and NoSQL in the same project, I can give you some hints:

  • move your SQL migrations to a folder inside the migrations folder. I’ll call it mysql.
  • all models that work with other than the default database driver should extend the right model

Running migrations should be done for both ways, either it’s local or in production.

For the default driver (i.e. when DB_CONNECTION is set to mongodb):

For the other driver (i.e. for MySQL):

Authenticating users with MongoDB

A big problem that I have encountered with MongoDB was when it was about the User. The User model extends an Authenticatable model. MongoDB does not support the default model that Laravel offers, so we’ll have to use the one that comes with the package:

In case you want to use Laravel Passport with MongoDB, make sure you use designmynight/laravel-mongodb-passport. It will provide you another Authenticatable class that will do the job for you!

NoSQL = NoJoins

NoSQL is good for some reasons over SQL: flexibility, speed, scalability, and integrity. One down from the ups’n’downs story is that we don’t have joins. We cannot use a third collection to join data between two other collections. However, the package has some cards hidden under the sleeve.

For example, a belongsToMany relationship would look like this:

Either you’re trying to access $user->roles or $role->users, you will need a third table called role_user that stores data.

In this case, MongoDB does something nasty: it allows you many-to-many, but it does not need a third table — it simply will store ids in each other’s model. Make sure that if you want to set custom foreign keys, you set the second parameter of the belongsToMany function to null.

After doing this, you’ll end up with something like this:

The User document looks like this:

The Role document looks like this:

At the same time, the rest of the other relationships, excepting morphToManyworks the same way as they do in SQL.

Schema is your playground

So, as long as NoSQL is schemaless, we can define it while we work with data, right? In MongoDB, we’re able to drop fields whenever we want.

This is our user document:

So, if we want to drop some fields, we can do it using the drop method:

In the end, it will simply remove the field from our document:

Pushing it into production

So, for quite a while, I’ve been running MongoDB in production. The truth is, that with the basic usage of the ORM with a small-configuration MongoDB like I have described in Setup MongoDB for Laravel on ploi.io, it just works without problems. Even for high-traffic apps, MongoDB is fast and reliable. On average, it consumes around 4 GB of RAM with around 600 million document reads, writes and deletes on an entire month, with an average of 600 writes and reads, combined, per second. What I don’t recommend is using it for caching — whenever you wanna cache, just remember to use memory over disk — it provides less friction and more speed of accessing and writing.

Written by

23 yo minimalist maker & laravel dev. founder of @safemenudotorg

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store