10 Essential MongoDB Interview Questions *

Toptal sourced essential questions that the best MongoDB developers and engineers can answer. Driven from our community, we encourage experts to submit questions and offer feedback.

Hire a Top MongoDB Developer Now
Toptal logois an exclusive network of the top freelance software developers, designers, finance experts, product managers, and project managers in the world. Top companies hire Toptal freelancers for their most important projects.

Interview Questions

1.

What are the pros and cons of normalizing data in a MongoDB database?

View answer

Just like in traditional RDBMSes, updating documents is fast for normalized data and relatively slower for denormalized data. On the other hand, reading documents is fast in denormalized data and slower for normalized data. Denormalized data is harder to keep in sync and takes up more space.

Note that in MongoDB, denormalized data is a more common expectation. This is because RDBMSes have inherent support for normalization and allow data to be managed as a separate concern, whereas NoSQL DBMSes like MongoDB do not inherently support normalization.

Instead, normalization requires that client applications carefully maintain integrity themselves. To help with this, it’s possible to run audits to ensure that app data conforms to expected patterns of referential integrity.

2.

How are sharding and replication similar to each other in MongoDB, and how are they different?

View answer

Both sharding and replication involve using more than one instance to host the database.

Replicas are MongoDB instances with the same data, hence the name. We use replicas to increase redundancy and availability.

With sharding, on the other hand, each shard instance has different data from its neighbors. We use sharding for horizontal scaling.

3.

What is the difference between the save and insert commands in MongoDB, and when do they act similarly?

View answer

Whether we provide an _id determines the expected result for both of these commands. Here is the expected outcome for each case.

  1. save command while providing an _id: In this case, the newly provided document replaces the document found with a matching _id.
  2. save command while not providing an _id: Inserts a new document.
  3. insert command while providing an _id: Gives a E11000 duplicate key error listing the collection, index, and duplicate key.
  4. insert command while not providing an _id: Inserts a new document.

As you can see, both the insert and save commands act similarly only when we do not provide an _id.

For example, the commands below would give us the same result:

db.cars.save({motor:"6-cylinder",color:"black"})
db.cars.insert({motor:"6-cylinder",color:"black"})

Apply to Join Toptal's Development Network

and enjoy reliable, steady, remote Freelance MongoDB Developer Jobs

Apply as a Freelancer
4.

What are some differences between BSON documents used in MongoDB and JSON documents in general?

View answer

JSON (JavaScript Object Notation)—like XML, for example—is a human-readable standard used for data exchange. JSON has become the most widely used standard for data exchange on the web. JSON supports data types like booleans, numbers, strings, and arrays.

BSON, however, is the binary encoding that MongoDB uses to store its documents. It is similar to JSON, but it extends JSON to support more data types, like Date. BSON documents, unlike JSON documents, are ordered. BSON usually takes less space than JSON and is faster to traverse. BSON, since it is binary, is also quicker to encode and decode.

5.

What is the difference between the $all operator and the $in operator?

View answer

Both the $all operator and the $in operator are used to filter documents in a subarray based on a conditional. Let us assume we have the following documents in a collection.

[{
        "name": "Youssef",
        "sports": [
            "Boxing",
            "Wrestling",
            "Football"
        ]
    },
    {
        "name": "Kevin",
        "sports": [
            "Wrestling",
            "Football"
        ]
    },
    {
        "name": "Eva",
        "sports": [
            "Boxing",
            "Football"
        ]
    }
]

Using $all as shown below will return only the first two documents:

db.users.find({
    sports: {
        $all: ["Wrestling", "Football"]
    }
})

Using $in will return all three documents:

db.users.find({
    skills: {
        $in: ["Wrestling", "Football"]
    }
})

The $all operator is stricter than the $in operator. $all is comparable to an AND conditional, and likewise $in resembles an OR conditional. That is to say, $all retrieves documents that satisfy all conditions in the query array, whereas $in retrieves documents that meet any condition in the query array.

6.

Assume there is a document with nested arrays that looks like the one below. How can you insert a “room” that has the name “Room 44” and size of “50” for a particular “house” that belongs to this user?

{
    "_id": "682263",
    "userName" : "sherif",
    "email": "sharief@aucegypt.edu",
    "password": "67834783ujk",
    "houses": [
        {
        "_id": "2178123",
        "name": "New Mansion",
        "rooms": [
            {
            "name": "4th bedroom",
            "size": "12"
            },
            {
            "name": "kitchen",
            "size": "100"
            }
        ]
        }
  ]
}
View answer

We can do so with the following code, commented inline:

db.users.update(
    { 
        "_id": ObjectId("682263"),
        "houses._id":"2178123"     // identify the id for the house that we want to update
    },
    { "$push":   
        {
            "houses.$.rooms":      // identify the array we want to push items into
                {                  
                    "name": "Room 44",      // this is the payload that needs to be pushed 
                    "size": "50"
                }
        }
    }
)
7.

Assume there is a collection named users that looks like the one below. How can you get all houses in the “Rabia” neighborhood?

[
    {
        "_id" : ObjectId("5d011c94ee66e13d34c7c388"),
        "userName" : "kevin",
        "email" : "kevin@toptal.com",
        "password" : "affdsg342",
        "houses" : [
            {
                "name" : "Big Villa",
                "neighborhood" : "Zew Ine"
            },
            {
                "name" : "Small Villa",
                "neighborhood" : "Rabia"
            }
        ]
    },

    {
        "_id" : ObjectId("5d011c94ee66e13d34c7c387"),
        "userName" : "sherif",
        "email" : "sharief@toptal.com",
        "password" : "67834783ujk",
        "houses" : [
            {
                "name" : "New Mansion",
                "neighborhood" : "Nasr City"
            },
            {
                "name" : "Old Villa",
                "neighborhood" : "Rabia"
            }
        ]
    },

]

View answer

Use the $filter aggregation operator. The query is:

db.users.aggregate([
    { $match: { 'houses.neighborhood': 'Rabia' } },
    {
        $project: {
            filteredHouses: {   // This is just an alias 
                $filter: {
                    input: '$houses', // The field name we are checking
                    as: 'houseAlias', // just an alias
                    cond: { $eq: ['$$houseAlias.neighborhood', 'Rabia'] }
                }
            },
            _id: 0
        }
    }

])

The first match query will return all documents that have a house with the name Rabia. The first query in the pipeline, {$match: {'houses.neighborhood': 'Rabia'}}, will return the whole collection. This is because both users have one house in the neighborhood “Rabia”.

This is the return for the first query in the pipeline

[
    {
        "_id" : ObjectId("5d011c94ee66e13d34c7c388"),
        "userName" : "kevin",
        "email" : "kevin@toptal.com",
        "password" : "affdsg342",
        "houses" : [
            {
                "name" : "Big Villa",
                "neighborhood" : "Zew Ine"
            },
            {
                "name" : "Small Villa",
                "neighborhood" : "Rabia"
            }
        ]
    },

    {
        "_id" : ObjectId("5d011c94ee66e13d34c7c387"),
        "userName" : "sherif",
        "email" : "sharief@toptal.com",
        "password" : "67834783ujk",
        "houses" : [
            {
                "name" : "New Mansion",
                "neighborhood" : "Nasr City"
            },
            {
                "name" : "Old Villa",
                "neighborhood" : "Rabia"
            }
        ]
    },

]

We do not want to display other user details nor display houses other than those in Rabia, so we will use the $filter operator inside the $project operator:

{
    $project: {
        filteredHouses: {   // This is just an alias 
            $filter: {
                input: '$houses', // The field name we check
                as: 'houseAlias', // just an alias
                cond: { $eq: ['$$houseAlias.neighborhood', 'Rabia'] }
            }
        },
        _id: 0
    }
}

The $$ prefix is required on houseAlias (instead of simply one $) due to nesting.

Here is the result we obtain at the end of the pipeline:

[
    {
        "filteredHouses" : [
            {
                "name" : "Old Villa",
                "neighborhood" : "Rabia"
            }
        ]
    },
    {
        "filteredHouses" : [
            {
                "name" : "Small Villa",
                "neighborhood" : "Rabia"
            }
        ]
    }
]
8.

Could you catch how the two queries below are different?

dealers.find({
    "$and": [
        {
            "length": {
                "$gt": 2000
            }
        },
        {
            "cars.weight": {
                "$gte": 800
            }
        }
    ]
});

dealers.find({
    "length": {
        "$gt": 2000
    },

    "cars.weight": {
        "$gte": 800
    }
});
View answer

Actually, they are exactly the same. MongoDB implicitly uses the $and operator for comma-separated queries. Which one to use is more a matter of preference than best practices.

9.

“Both writes and reads become faster when you add more slaves to a replica set.” Is this statement true or false? Why?

View answer

False. All write operations are done only on the master. On the other hand, read operations can be made on any instance—slave or master. Therefore, only reads become faster when you add more slaves to a replica set.

10.

A staple feature of relational database systems is the JOIN clause. What is the equivalent in MongoDB, and does it have any known limitations?

View answer

The $lookup operator is the equivalent of JOIN.

Here is an example of a nested lookup in MongoDB.

Assume we have three collections (authors, authorInfo, and userRole) with the following data:

// authors collection
[
    {
        "_id" : ObjectId("5d0127aaee66e13d34c7c389"),
        "address" : "32 Makram Ebeid Street",
        "isActive" : true,
        "authorId" : "121"
    }
]

// authorInfo collection
[
    {
        "_id" : ObjectId("5d0f726bac65f929d0fa98b2"),
        "authorId" : "121",
        "description" : "A description"
    }
]

// userRole collection
[
    {
        "_id" : ObjectId("5d012a08ee66e13d34c7c38f"),
        "userId" : "121",
        "role" : "manager"
    }
]

What if we want to join the authors from all three collections? In the SQL world, a JOIN query for this might look like:

SELECT a._id, a.address, b.description, c.role
  FROM authors a
  INNER JOIN "authorInfo" b ON b."authorId" = a."authorId"
  INNER JOIN "userRole" c ON c."userId" = a."authorId"

But in MongoDB, here is the equivalent query:

db.authors.aggregate([

    // Join with authorInfo table
    {
        $lookup:{
            from: "authorInfo",       // connecting authorInfo collection
            localField: "authorId",   // name of field in the authors collection
            foreignField: "authorId", // name of field in the authorInfo collection
            as: "authorInfoAlias"     // any alias
        }
    },
    {   $unwind:"$authorInfoAlias" }, // use the alias here

    // Join with userRole collection
    {
        $lookup:{
            from: "userRole", 
            localField: "authorId", 
            foreignField: "userId",
            as: "authorRoleAlias"
        }
    },
    {   $unwind:"$authorRoleAlias" },
    {   
        $project: {                                          // Just projecting our data.
            _id : 1,
            address : 1,
            description : "$authorInfoAlias.description",
            role : "$authorRoleAlias.role",
        } 
    }

The $ prefix is required for aliases to work.

The result of this query is the following:

[
    {
        "_id" : ObjectId("5d0127aaee66e13d34c7c389"),
        "address" : "32 Makram Ebeid Street",
        "description" : "A description",
        "role" : "manager"
    }
]

The major drawback of the $lookup operator is that it does not work in sharded collections.

It’s worth noting that, instead of looking for a direct equivalent to JOIN, a more common approach with MongoDB developers is to simple denormalize the data, precluding the need for a JOIN equivalent.

There is more to interviewing than tricky technical questions, so these are intended merely as a guide. Not every “A” candidate worth hiring will be able to answer them all, nor does answering them all guarantee an “A” candidate. At the end of the day, hiring remains an art, a science — and a lot of work.

Why Toptal

Tired of interviewing candidates? Not sure what to ask to get you a top hire?

Let Toptal find the best people for you.

Hire a Top MongoDB Developer Now

Our Exclusive Network of MongoDB Developers

Looking to land a job as a MongoDB Developer?

Let Toptal find the right job for you.

Apply as a MongoDB Developer

Job Opportunities From Our Network

Submit an interview question

Submitted questions and answers are subject to review and editing, and may or may not be selected for posting, at the sole discretion of Toptal, LLC.

* All fields are required

Looking for MongoDB Developers?

Looking for MongoDB Developers? Check out Toptal’s MongoDB developers.

Marcin Bodnar

Freelance MongoDB Developer
PolandToptal Member Since March 1, 2019

Marcin is a senior software engineer focused on web development with over 15 years of proven professional experience (in both startups and enterprise environments) and more than 300 successful web projects. When it comes to development, he believes that motivation, communication, high resistance to stress, and team culture are crucial when bringing the clients' expectations to life. Marcin equally enjoys working in a team or independently.

Show More

Petr Rusanov

Freelance MongoDB Developer
NetherlandsToptal Member Since October 19, 2015

Petr is a full-stack engineer with a 17-year record of optimizing code, costs, and user experiences. He excels in crafting secure, readable, and reliable code for cloud-native services. He is proficient in Go, Node.js, PostgreSQL, MongoDB, Bigtable, GCP/AWS/Azure, React/Vue, Kubernetes, ArgoCD, Docker, and Terraform. Petr focuses on delivering exceptional user experiences and optimizing large-scale applications for peak performance and cost efficiency.

Show More

Silvio Di Stefano

Freelance MongoDB Developer
FranceToptal Member Since November 29, 2013

Silvio is a software engineer specializing in the development, hosting, and maintenance of top-quality websites. He has collaborated with numerous teams around the world, striving to provide high-end service and support. He released his first website in PHP at age 14 and is an advocate for TDD.

Show More

Toptal Connects the Top 3% of Freelance Talent All Over The World.

Join the Toptal community.

Learn more