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开发人员Interview Questions
就像传统的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.
How are sharding and replication similar to each other in MongoDB, and how are they different?
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. 我们使用分片进行水平扩展.
Whether we provide an _id
确定这两个命令的预期结果. 以下是每种情况的预期结果.
-
save
命令,同时提供_id
: In this case, the newly provided document replaces the document found with a matching_id
. -
save
命令,而不提供_id
: Inserts a new document. -
insert
命令,同时提供_id
: Gives aE11000 duplicate key error
列出集合、索引和重复键. -
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开发人员职位
What are some differences between BSON documents used in MongoDB and JSON documents in general?
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.
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 条件.
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"
}
]
}
]
}
我们可以用下面的代码来实现,内联注释:
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"
}
}
}
)
假设有一个名为 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"
}
]
},
]
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"
}
]
}
]
您能发现下面两个查询的不同之处吗?
dealers.find({
"$and": [
{
"length": {
"$gt": 2000
}
},
{
"cars.weight": {
"$gte": 800
}
}
]
});
dealers.find({
"length": {
"$gt": 2000
},
"cars.weight": {
"$gte": 800
}
});
实际上,它们完全一样. MongoDB implicitly uses the $and
operator 用于逗号分隔的查询. Which one to use is more a matter of preference than best practices.
“Both writes and reads become faster when you add more slaves to a replica set.这个说法是对还是错? Why?
False. All write 操作只在主服务器上进行. On the other hand, read 操作可以在任何实例上进行——从实例或主实例. Therefore, only reads become faster when you add more slaves to a replica set.
关系数据库系统的一个主要特性是 JOIN
clause. What is the equivalent in MongoDB, and does it have any known limitations?
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
提出面试问题
Submitted questions and answers are subject to review and editing, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.
寻找MongoDB开发人员?
Looking for MongoDB Developers? 看看Toptal的MongoDB开发人员.
Marcin Bodnar
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 MorePetr Rusanov
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 MoreSilvio Di Stefano
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 MoreToptal Connects the Top 3% 世界各地的自由职业人才.
Join the Toptal community.