MongoDB 基础面试题
本节将聚焦 MongoDB 面试中常见的基础性问题。
解释一下 BSON 存储格式。
BSON 是二进制的 JavaScript 对象表示法。它以二进制编码格式存储序列化的 JSON 文档,并通过支持额外的数据类型(如 Date、ObjectId 和正则表达式)来扩展 JSON 的能力。
一个 BSON 文档通常包含三部分:文档大小、字段元素(如数据类型、名称和值)以及空字符终止符,全部以二进制格式编码。
下表展示了 BSON 与 JSON 的差异,尤其是 BSON 对 JSON 能力的扩展:
|
特性 |
JSON |
BSON |
|
编码格式 |
基于文本 |
二进制 |
|
支持的数据类型 |
String、Number、Boolean 等 |
JSON 类型 + Date、ObjectId、正则表达式 |
|
可读性 |
人类可读 |
机器可读 |
|
使用场景 |
数据交换 |
MongoDB 中的数据存储 |
MongoDB 中的集合是什么?
MongoDB 集合是存储在同一数据库中的一组文档。它类似于关系型数据库中的表,其中集合中的每个文档相当于表中的一行。但集合没有固定的模式,这意味着集合中的文档可以具有不同的数据类型。
如何在 MongoDB 中查询文档?
在 MongoDB 中,您可以使用 find() 方法查询文档。要查询集合中的所有文档,使用 db.collection_name.find()。find 方法有两个输入参数:query 和 projection。query 参数用于筛选满足特定条件的文档。
query 参数语法:
db.collection_name.find({condition})
第二个是投影参数,用于指示在输出中包含或排除哪些列。将 1 赋给您想要获取的列。语法如下:
db.collection_name.find({},{column1: 1, column2: 1})
find() 和 findOne() 有什么区别?
find() 方法返回一个指向多个匹配查询条件的文档的游标。它通过遍历所有结果并获取匹配的文档来工作。相比之下,findOne() 方法只返回首个匹配的文档。
MongoDB 中的 _id 字段是什么?
存储在集合中的每个文档都需要一个唯一标识符。该 _id 字段充当主键,用于唯一地标识集合中的文档。
MongoDB 中级面试题
现在,我们来看一些面试官通常期望您掌握的 MongoDB 核心概念。
MongoDB 如何存储大型图片和视频?
传统上,MongoDB 不允许存储大于 16 MB 的文档。不过,它有一项名为 GridFS 的特殊规范,用于存储和检索超过 16 MB 的文件。它会将文件拆分为更小且大小相等的块,并在内部将这些块作为独立文档存储。
下表总结了 MongoDB 如何使用 GridFS 存储大文件:
|
步骤 |
说明 |
|
文件分块 |
将文件拆分为 255 KB 或更小的块 |
|
元数据存储 |
在 |
|
分块存储 |
在 |
|
检索 |
从已存储的分块重建文件 |
MongoDB 如何确保高可用性?
MongoDB 通过副本集实现高可用性。副本集在多个节点上存储数据的不同副本,这样当某个节点发生故障时,其他节点可以接管。
MongoDB 中的分片(sharding)是什么?
分片使 MongoDB 实现水平扩展。当单个实例无法管理庞大的数据集时,MongoDB 会将数据拆分为更小的分块,并分布到多个服务器(即分片)上。
下表阐明了复制与分片之间的差异:
|
特性 |
复制(Replication) |
分片(Sharding) |
|
目的 |
高可用性 |
大数据集的可扩展性 |
|
实现方式 |
副本集(多份拷贝) |
数据在分片间分区存储 |
|
使用场景 |
容错 |
大型数据库的负载均衡 |
|
数据分布 |
所有节点存储相同数据 |
数据分布在各个节点上 |
MongoDB 中的副本集(replica set)是什么?
MongoDB 的副本集是一组维护相同数据集的实例。它们用于需要高可用性的应用,因为当某个实例出现问题时,系统会自动切换到副本集中下一个可用节点。
解释 MongoDB 的聚合(aggregation)概念。
MongoDB 可以从多个文档中汇总数据并处理后返回单一结果。这涉及聚合管道,文档会经过若干阶段——每个阶段的输出作为下一个阶段的输入。一个典型的管道可能包括 match、group 和 sort 等阶段:
- Match:根据给定条件筛选文档。
- Group:执行聚合操作。
- Sort:按所需方式对最终结果排序。
什么是 MongoDB 的固定集合(capped collection)?
固定集合具有固定大小和文档数量上限。当达到上限时,它会自动覆盖最旧的文档,存储最新信息。该特性使其非常适合日志和缓存等使用场景。
MongoDB 高级面试题
本节我们来看一些常见的 MongoDB 高级面试题与答案。
MongoDB 是否支持 ACID 事务?
在 4.0 版本之前,MongoDB 仅对单个文档支持 ACID 事务。引入多文档 ACID 事务后,开发者现在可以在同一集合内的多文档之间确保ACID 属性。
什么是 MongoDB 中的 map-reduce?
Map-reduce 是一种数据处理范式,可对大型数据集执行操作并输出聚合结果。MongoDB 提供内置的 mapReduce() 函数,包含 map 和 reduce 两个阶段。
在 map 阶段,函数处理集合中的每个文档并生成键值对。在 reduce 阶段,这些键值对被聚合并执行相关操作。
例如,如果您有一个文本文档集合,map 函数会将每个单词转换为一个键,并为其赋值 1。reduce 函数随后对每个键的值求和,以统计整个集合中各个单词的出现次数。
解释 MongoDB 中的 TTL 索引。
生成的数据应定期审查并在不再需要时移除;否则,您将耗尽用于容纳最新信息的资源。
MongoDB 提供生存时间(TTL)索引,用于简化过期文档的删除。您只需指定文档的保留时长,TTL 会在指定时间过去后自动将其删除。
下表介绍了 MongoDB 可用的索引类型及其使用场景:
|
索引类型 |
说明 |
示例用例 |
|
单字段 |
对单个字段建立索引 |
为邮箱建立索引以加速查找 |
|
复合 |
对多个字段建立索引 |
按 |
|
文本 |
对字符串字段进行全文搜索 |
通过关键词搜索博客文章 |
|
TTL |
自动删除已过期的文档 |
在特定时间后清理日志 |
|
地理空间 |
支持基于位置的查询 |
查找附近的餐馆 |
MongoDB 是否具备备份与恢复功能?
MongoDB 可通过 mongodump 工具进行数据备份。该工具会创建数据的二进制备份,您可在需要时导入。另一种选择是使用第三方云解决方案或MongoDB Atlas(云服务)来自动化备份流程。
MongoDB 提供 mongorestore 工具,用于从备份的 BSON 文件中导入数据。此外,第三方云解决方案还提供自动化恢复功能,从而最大限度减少停机时间。
如何优化 MongoDB 查询?
以下是一些可用于优化 MongoDB 查询的做法:
- 索引会存储关于文档的信息,有助于快速定位所需数据。因此,创建索引可以提升查询性能。
- 如果您知道所需的列,请使用投影方法仅返回这些字段,以获得更好的性能。
- 避免使用代价高昂的操作(如正则表达式);请改用前缀搜索或已建立索引的字段。
- 选择合适的分片键,尤其是在读取密集的工作负载下。
解释 MongoDB 的预写日志(journaling)。
当执行写操作时,MongoDB 会先将其记录到日志文件,然后再写入数据库文件。这些日志可确保在系统故障或崩溃时,已提交的写操作能够被快速恢复。
MongoDB 编码类面试题
编码题通常考察您将 MongoDB 概念用代码实现的能力。它们会测试您的语法、编码实践,以及您对 MongoDB 工具与函数的高效运用。
如何在 MongoDB 中创建索引?
MongoDB 通过 createIndex() 函数创建多种类型的索引,如单字段索引、文本索引和二维索引。该方法有两个输入参数:用于定义索引字段的 keys,以及其他选项。
语法:
db.collection.createIndex(keys, options)
- Keys:
{ field1: 1, field2: -1, ... },1 表示升序,-1 表示降序 - Options:
{unique: true}、{sparse: true}、{ expireAfterSeconds: 3600 }
示例:
db.users.createIndex({ email: 1 }, { unique: true });
如何在 MongoDB 中实现聚合?
聚合通常包含三个阶段:match、group 和 sort。下面看看如何用代码实现。
“products” 文档示例:
[
{ "_id": 1, "product_id": "t2409", "amount": $250, "status": "done" },
{ "_id": 2, "product_id": "t2009", "amount": $300, "status": "done" },
{ "_id": 3, "product_id": "t1309", "amount": $150, "status": "pending" },
{ "_id": 4, "product_id": "t1919", "amount": $480, "status": "done" },
{ "_id": 5, "product_id": "t5459", "amount": $120, "status": "pending" },
{ "_id": 6, "product_id": "t3829", "amount": $280, "status": "done" }
]
$match:根据条件筛选文档$group:对数据分组并执行聚合操作$sort:按需对输出文档排序
示例:
db.products.aggregate([
{ $match: { status: "completed" } },
{ $group: { _id: "$product_id", totalAmount: { $sum: "$amount" },
{ $sort
]);
如何在 MongoDB 中实现等价于 SQL 的连接(join)?
MongoDB 提供如 $lookup 等聚合运算符来实现与 SQL join 等价的操作。
语法:
db.collection_1_name.aggregate([
{
$lookup: {
from: "collection_2_name", // The other collection to join with
localField: "field_in_collection_1", // The field on which you want to join
foreignField: "field_in_collection_2", // The field from the second collection you want to perform join operation
as: "result_field" // The name of the new field to store the joined result
}
}
])
示例:
假设您有订单与产品两个集合,数据如下:
“Orders” 集合:
[
{ "_id": 1, "product_id": 101, "order_amount": 250 },
{ "_id": 2, "product_id": 102, "order_amount": 300 },
{ "_id": 3, "product_id": 101, "order_amount": 150 }
]
“Products” 集合:
[
{ "_id": 3789, "product_id": 102, "product_price": $100},
{ "_id": 3970, "product_id": 103, "product_price": $297},
{ "_id": 3509, "product_id": 101, "product_price": $300},
]
连接操作:
db.orders.aggregate([
{
$lookup: {
from: "products",
localField: "customer_id",
foreignField: "_id",
as: "customer_info"
}
}
])
如何在 MongoDB 中建模一对多关系?
您可以使用嵌入式文档的数据模型来表示一对多关系。例如,一个团队可以有多名员工,您可以如下进行嵌入:
数据:
// team details
{
_id: "Datascience"
company_name: "DataCamp"
team_name: "Data leaders"
}
// employee one
{
name: "John"
employee_id: "t009456"
email: johnsmith@datacamp.com
}
// employee two
{
name: "Emily"
employee_id: "t8068ms"
email: emilyjones@datacamp.com
}
一对多嵌入式文档:
{
"_id": "Datascience",
"company_name": "DataCamp",
"team_name": "Data leaders",
"employees": [
{
"name": "John",
"employee_id": "t009456",
"email": "[email protected]"
},
{
"name": "Emily",
"employee_id": "t8068ms",
"email": "[email protected]"
}
]
}
面向 DBA 的 MongoDB 场景题
面试官会将您置于具有挑战性的情境中,评估您的应对方式。这有助于了解您在使用 MongoDB 处理实时问题时的能力。
假设您在如下方式对数据库 “orders” 执行搜索操作。如何调试查询为何缓慢?
df.orders.find({
customer_id: 'yop89'
ordered_items: {
product_id: 'toi45'
product_id: 'tac87'
}
});
首先,您应将分析器级别设为 1,以仅记录慢查询:
db.setProfilingLevel(1, { slowms: 100 }); // Logs queries slower than 100ms
现在,以下代码会给出更多细节,如操作类型、耗时,以及扫描的键或文档数。这些信息有助于找出运行缓慢的查询:
db.system.profile.find({ millis: { $gt: 100 } }).sort({ millis: -1 }).limit(10);
在上述场景中,如何提升慢查询的性能?
根据上述代码的输出,如果查询扫描了整个集合,请在 customer_id 和 ordered_items 上创建索引。索引可以减少被扫描的文档数量,从而提升查询执行时间。
db.orders.createIndex({ customer_id: 1, "ordered_items.product_id": 1});
在分片中,如果一个分片过载而其他分片空闲,如何进行平衡?
两种潜在问题是分片键选择不当,以及数据在分片间分布不均。
方案 1: 选择合适的分片键
- 选择高基数的列作为分片键,即分片键应具有大量唯一值。
- 如果您的工作负载以写为主,确保分片键不会将所有写入集中到单个分片。
- 选择与最常见查询相匹配的分片键。例如,如果您的查询经常在某个字段上进行连接,那么该字段可能是有效的分片键。
方案 2: 重新平衡不均匀的分布
下面的命令可提供分片间数据分布的概览。如果分块分布不均,请启用平衡器。
sh.status()
下面的命令可获取平衡器的状态。如果处于禁用状态,使用后一个命令将其启用。
sh.getBalancerState()
sh.enableBalancing("db_name.collection_name")
从 RDBMS 迁移到 MongoDB 可能会遇到哪些挑战?
将关系型数据库操作映射到 NoSQL 的对应实现可能会比较困难。
- 例如,在 MongoDB 中并没有像 SQL 那样直观的连接操作;您需要使用聚合框架来实现类似功能。
- 另一项挑战是,存储在结构化表中的数据需要转换为适配 MongoDB 的 BSON 存储格式。
- 此外,虽然 RDBMS 提供健全的 ACID 合规性,但 MongoDB 仅在文档级别提供 ACID 属性,这意味着复杂的 ACID 事务可能需要额外关注。
MongoDB 面试准备技巧
要拿下 MongoDB 面试,既要深刻理解概念,也要具备扎实的实战能力。必须加强您对NoSQL 数据库的理解,熟练掌握MongoDB 语法,并接触多种 MongoDB 故障场景并学会解决。
以下是我帮助您通过下一场 MongoDB 面试的最佳建议:
- 夯实基础: 无论是入门岗位还是高级职位,基础都必考。因此要理解 MongoDB 的架构、存储类型、语法及支持的操作。
- 高级主题: 您需要了解复制、聚合、分片和索引等高级概念在 MongoDB 中如何工作,并在需要时能够实现。
- 真实场景: 面试官常常会考察您在不同职场场景下如何管理 MongoDB 数据库。例如,可能会问您如何将现有的 RDBMS 数据库迁移到 MongoDB。在更高级的面试中,您或许会被给出一个场景并要求编写代码来解决。
- 阅读过往经验: 了解该公司的过往面试经验有助于把握题型与流程,从而更有针对性地准备。我个人会使用 Glassdoor、Blind、YouTube 和 LinkedIn 等平台查阅过往面试经验。
- 模拟面试: 模拟面试有助于评估您的优势与短板,也能让您提前适应面试环境,从而在正式面试时更自信从容。
- 软技能: 能清晰表达复杂主题对打动面试官至关重要。因此,请提升您的沟通与展示能力。
- 认证: MongoDB 认证可作为您专业能力的证明。它能加深您对该领域的理解,并提升被录用的机会。这里有一份获取 MongoDB 认证的完整指南。
结语
MongoDB 是一款功能强大的 NoSQL 数据库,具备灵活的模式,能够支持现代应用。因此,在软件开发领域,对其专业能力的需求非常旺盛。
在本文中,我们梳理了从基础到编码以及情景题在内的关键面试问题。此外,文末的技巧将提升您在面试中的成功几率。
要进一步加深对 MongoDB 的理解,建议学习诸如 Python 中的 MongoDB与 NoSQL 概念等课程。

Srujana 是一名自由职业技术写作者,拥有计算机科学四年制学位。她擅长撰写各类主题的内容,包括数据科学、云计算、开发、编程、安全等众多领域。她热爱经典文学,也喜欢探索新的旅行目的地。
到目前为止,我参加过许多数据科学与数据库相关的面试。企业越来越青睐熟悉 NoSQL 数据库的专业人士。MongoDB 是最灵活的数据库之一,能够以最少的停机时间支持可扩展的现代应用。
在本文中,我整理了我在面试中遇到的一些问题,并结合同事们的面试经历给出了相应的见解。
什么是 MongoDB?
MongoDB 是一种No-SQL 数据库,采用灵活、无模式的架构存储数据。与传统表不同,它使用文档和集合以一种类 JSON 的格式(称为 BSON)保存记录。该格式允许 MongoDB 以分层模型存储多种数据类型。
由于 MongoDB 没有固定模式,它支持任意类型的数据存储,是实时分析与数据流的理想选择。此外,现代应用常常会经历快速增长或不可预测的流量,MongoDB 对此尤为得心应手。例如,MongoDB 支持水平扩展,可通过增加服务器来应对不断增长的负载。