A common gotcha with Mongoose that cost me a hackathon and will probably save you a lot of frustration.
Photo by Kyle Glenn on Unsplash
Mongoose is a MongoDB object modeling tool. It works as a middleware to perform operations on MongoDB. If you have been working with Node.js and MongoDB, you must have surely come across Mongoose. If you have started working with it recently, by following tutorials, like me, you might have missed this common gotcha.
Table of contents
Open Table of contents
The experiment
We will create a simple express server to demonstrate how Mongoose will fail silently even when the connection to the database is not created. I hope you already have Node.js and npm installed on your system and create a new folder to create our example app in. Now open your terminal or git bash (You can get it here: https://git-scm.com/downloads) if on windows in that folder. We will Initialise our Node app using the below command.
npm init -y
We will now install all the required dependencies.
npm i express mongoose
We will then create a new file called ‘index.js’ to hold our Node.js code and let us first paste the basic express app code in it.
const express = require("express");
const app = express();
app.listen(3000, () => {
console.log("Your app is listening on port 3000");
});
We will now add code from the Mongoose homepage to our express app and not add a Mongoose connection. We will also create a route to demonstrate how this can cause problems. So our final index.js file should look like this.
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const Cat = mongoose.model("Cat", { name: String });
app.get("/", function (request, response) {
Cat.findOne({ name: "Hero" }, function (error, foundCat) {
response.send(foundCat);
});
});
app.listen(3000, () => {
console.log("Your app is listening on port 3000");
});
Now we will start our server using the below command.
node index.js
Now let us open our browser and go to http://localhost:3000/ and your browser should keep loading and you would think Mongoose would throw an error in the terminal or git bash but to our surprise, nothing.
The cause
Mongoose uses something called Operation Buffering. It buffers model function calls internally so that you can start using your models immediately, without waiting for Mongoose to establish a connection to MongoDB. Basically, all function calls you make on Mongoose models get stored in a buffer so they can execute when a connection is established to the database. This can cause confusion as no error message is shown when that happens.
The fix
You can fix this by setting Operation Buffering to false like this:
mongoose.set("bufferCommands", false);
But, you should also note that buffering is also responsible for waiting until Mongoose creates collections. If you disable buffering, you should also disable the autoCreate
option and use the createCollection()
option. You can and I suggest you do, read more about it here: https://mongoosejs.com/docs/connections.html#buffering
Conclusion
Even though the problem in this simple example may seem obvious, when you are working on a project that is structured and the database connection is modularised into a different file, you could easily forget to import it. Or even if you did import it, you could forget to invoke it if you are exporting it as a function like I did which cost me a hackathon. I hope you were able to learn something new and hope this saves someone else the frustration it caused me.