Unique indexes with MongoDB and Mongoose

Even though I’ve been using MongoDB for the last few years, I’m still very much
a noob when it comes to a lot of things.

One of those things would be unique indexes.

Generally speak, I interact with MongoDB three different ways:

  1. I write code that explicitly creates something with no duplicate concerns
  2. I perform an update on a record using it’s primary key / ID
  3. I will do a findOneAndUpdate with the upsert flag set to true.

Channelling a bit of my Pythonic roots, I don’t really like asking for
permissions. In an age of Promises, I’m writing more and more try / catch
blocks that just try to do stuff and will handle the fall out if an error is
encountered.

Back when the world was dominated by RDBMSes and I was using MySQL for just
about everything, I would approach tables with unique indexes in the same
Pythonic way, just try it and see.

This would result in code that would try to write to a table (sans a lookup to
see if a record already exists) and if there was an error, I would check the
error code to figure out if the record already existed or if something else
happened.

That would result in code that didn’t do an unnecessary lookup at the beginning
and would still be able to handle collisions against the unique key.

I wanted to do the same thing with MongoDB, but back to my noob status, I had
never actually created any indexes on a collection (don’t judge 😉

Fortunately, Mongoose (our ODM of choice) makes things very simple and you can
define an index on individual fields as well as a compound index that spans
multiple fields.

I needed both and thought it was worth putting a post together about it as I had
to root around for a bit to find what I was looking for.

Single Field Unique Indexes

To add a unique index to a single column, we simply add a unique property to
the field.

Let’s say we have a collection of fruits to track which ones are edible and we
want to make the name of the fruit to be unique. We’d simply add the additional
property and Mongoose will take care of the rest!

const mongoose = require('mongoose'

const fruitSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    unique: true,
  },
  isEdible: {
    type: Boolean,
    default: false,
  },


module.exports = mongoose.model('Fruit', fruitSchema

Multiple Field (Compound) Unique Indexes

Adding an index to a single field is pretty trivial, but if you want to add an
index to more than one field, simply adding the unique property isn’t going to
cut it.

For this example, let’s say we have a collection that represents different mango
varieties and their country of origin and whether or not the fruit is the country
of origin’s national fruit.

In this scenario, we could make the variety and country of origin unique.

const mongoose = require('mongoose'

const mangoSchema = new mongoose.Schema({
  variety: {
    type: String,
    required: true,
  },
  countryOfOrigin: {
    type: String,
    required: true,
  },


mangoSchema.index({
  variety: 1,
  countryOfOrigin: 1,
}, {
  unique: true,


module.exports = mongoose.model('Mango', mangoSchema

Internally, Mongoose will take care of creating the defined indexes when the
process is restarted and you’ll be good to go!

Comment below if you think I should have went with indices instead of
indexes for this particular post 😉

Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.