10个MongoDB面试必备问题 *

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.

现在聘请一名顶级MongoDB开发人员
Toptal logois an exclusive network of the top freelance software developers, designers, finance experts, product managers, 和世界上的项目经理. 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

就像传统的rdbms一样, 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. 我们使用副本来增加冗余和可用性.

With sharding, on the other hand, each shard instance has different data from its neighbors. 我们使用分片进行水平扩展.

3.

的区别是什么 save and insert 命令在MongoDB中,以及何时它们的行为类似?

View answer

Whether we provide an _id 确定这两个命令的预期结果. 以下是每种情况的预期结果.

  1. save 命令,同时提供 _id: In this case, the newly provided document replaces the document found with a matching _id.
  2. save 命令,而不提供 _id: Inserts a new document.
  3. insert 命令,同时提供 _id: Gives a E11000 duplicate key error 列出集合、索引和重复键.
  4. insert 命令,而不提供 _id: Inserts a new document.

As you can see, both the insert and save 命令的行为与此类似,只有当我们不提供 _id.

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

db.cars.保存({电动机:“6缸”,颜色:“黑色”})
db.cars.插入({电动机:“6缸”,颜色:“黑色”})

申请加入Toptal的发展网络

并享受可靠、稳定、远程 自由MongoDB开发人员职位

Apply as a Freelancer
4.

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

View answer

JSON (JavaScript对象表示法),类似于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. 与JSON文档不同,BSON文档是有序的. 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.

的区别是什么 $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 如下所示将只返回前两个文档:

db.users.find({
    sports: {
        $all:[“摔跤”,“足球”]
    }
})

Using $in 将返回所有三个文档:

db.users.find({
    skills: {
        $in:[“摔跤”,“足球”]
    }
})

The $all 操作符比 $in operator. $all is comparable to an AND conditional, and likewise $in resembles an OR conditional. That is to say, $all 检索满足的文档 all 条件,而 $in 检索满足的文档 any 条件.

6.

Assume there is a document with nested arrays 看起来像下面这个. 你如何插入一个有 name “Room 44” and size 对于属于该用户的特定“房子”的值为“50”?

{
    "_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

我们可以用下面的代码来实现,内联注释:

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.

假设有一个名为 users 看起来像下面这个. How can you get all houses 在"拉比亚"附近?

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

    {
        "_id": ObjectId("5d011c94ee66e13d34c7c387"),
        "userName" : "sherif",
        "email" : "sharief@chinaqinyu.com",
        password:“67834783ujk”,
        "houses" : [
            {
                "name" : "New Mansion",
                “邻里”:“纳斯尔城”
            },
            {
                "name" : "Old Villa",
                "neighborhood" : "Rabia"
            }
        ]
    },

]

View answer

Use the $filter aggregation operator. The query is:

db.users.aggregate([
    { $match: { 'houses.neighborhood': 'Rabia'}},
    {
        $project: {
            filteredHouses:{//这只是一个别名 
                $filter: {
                    input: '$houses', //我们要检查的字段名
                    如:'houseAlias', //只是一个别名
                    cond: {$eq: ['$$houseAlias.neighborhood', 'Rabia'] }
                }
            },
            _id: 0
        }
    }

])

The first match query will return all documents that have a house with the name Rabia. 管道中的第一个查询, {$match: {'houses.neighborhood': 'Rabia'}},将退还全部藏品. This is because both users have one house in the neighborhood “Rabia”.

这是管道中第一个查询的返回值

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

    {
        "_id": ObjectId("5d011c94ee66e13d34c7c387"),
        "userName" : "sherif",
        "email" : "sharief@chinaqinyu.com",
        password:“67834783ujk”,
        "houses" : [
            {
                "name" : "New Mansion",
                “邻里”:“纳斯尔城”
            },
            {
                "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:{//这只是一个别名 
            $filter: {
                input: '$houses', //我们检查的字段名
                如:'houseAlias', //只是一个别名
                cond: {$eq: ['$$houseAlias.neighborhood', 'Rabia'] }
            }
        },
        _id: 0
    }
}

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

下面是我们在管道末端得到的结果:

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

您能发现下面两个查询的不同之处吗?

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

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

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

实际上,它们完全一样. MongoDB implicitly uses the $and operator 用于逗号分隔的查询. 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.这个说法是对还是错? Why?

View answer

False. All write 操作只在主服务器上进行. On the other hand, read 操作可以在任何实例上进行——从实例或主实例. Therefore, only reads become faster when you add more slaves to a replica set.

10.

关系数据库系统的一个主要特性是 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.

下面是MongoDB中嵌套查找的一个示例.

假设我们有三个集合(authors, authorInfo, and userRole) with the following data:

// authors collection
[
    {
        "_id": ObjectId("5d0127aaee66e13d34c7c389"),
        “地址”:“Makram Ebeid街32号”,
        "isActive" : true,
        "authorId" : "121"
    }
]

// authorInfo collection
[
    {
        "_id": ObjectId("5d0f726bac65f929d0fa98b2"),
        "authorId" : "121",
        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 对此的查询可能如下所示:

SELECT a._id, a.address, b.description, c.role
  FROM authors a
  INNER JOIN "authorInfo" b ON."authorId" = a."authorId"
  内部连接“userRole”c ON."userId" = a."authorId"

但在MongoDB中,这里是等效的查询:

db.authors.aggregate([

    //与authorInfo表连接
    {
        $lookup:{
            from: "authorInfo", //连接authorInfo集合
            localField: "authorId",   // name of field in the authors collection
            foreignField: "authorId", // name of field in the authorInfo collection
            as: "authorInfoAlias" //任意别名
        }
    },
    {$unwind:"$authorInfoAlias"}, //在这里使用别名

    //连接userRole集合
    {
        $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 $ 前缀是别名工作所必需的.

查询的结果如下:

[
    {
        "_id": ObjectId("5d0127aaee66e13d34c7c389"),
        “地址”:“Makram Ebeid街32号”,
        "description": "描述";
        "role" : "manager"
    }
]

The major drawback of the $lookup 操作符不能在分片集合中工作.

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, 所以这些只是作为一个指南. Not every “A” candidate worth hiring will be able to answer them all, 回答所有问题也不能保证成为A级考生. At the end of the day, 招聘仍然是一门艺术,一门科学,需要大量的工作.

Why Toptal

厌倦了面试候选人? 不知道该问什么才能让你得到一份好工作?

让Toptal为你找到最合适的人.

现在聘请一名顶级MongoDB开发人员

我们的MongoDB开发者专属网络

希望找到一份MongoDB开发人员的工作?

让Toptal为你找到合适的工作.

申请成为MongoDB开发人员

工作机会从我们的网络

提出面试问题

Submitted questions and answers are subject to review and editing, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.

* All fields are required

寻找MongoDB开发人员?

Looking for MongoDB Developers? 看看Toptal的MongoDB开发人员.

Marcin Bodnar

自由MongoDB开发人员
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. 说到发展, 他相信动机, communication, high resistance to stress, and team culture are crucial when bringing the clients' expectations to life. Marcin同样喜欢团队合作或独立工作.

Show More

Petr Rusanov

自由MongoDB开发人员
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. 他精通围棋和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

自由MongoDB开发人员
FranceToptal Member Since November 29, 2013

Silvio is a software engineer specializing in the development, hosting, 并维护高质量的网站. 他与世界各地的许多团队合作过, 努力提供高端的服务和支持. He released his first website in PHP at age 14 and is an advocate for TDD.

Show More

Toptal Connects the Top 3% 世界各地的自由职业人才.

Join the Toptal community.

Learn more