跳至主要内容

2026 年最常见的 25 道 MongoDB 面试题与答案

本指南涵盖关键的 MongoDB 面试问题,从基础到高级,并包含代码示例、真实场景与专家建议,助您顺利斩获 Offer!
Srujana Maddula
Srujana Maddula

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续继续即表示您接受我们的 使用条款,我们的 隐私政策 ,并且您的数据存储在美国。

到目前为止,我参加过许多数据科学与数据库相关的面试。企业越来越青睐熟悉 NoSQL 数据库的专业人士。MongoDB 是最灵活的数据库之一,能够以最少的停机时间支持可扩展的现代应用。

在本文中,我整理了我在面试中遇到的一些问题,并结合同事们的面试经历给出了相应的见解。

什么是 MongoDB?

MongoDB 是一种No-SQL 数据库,采用灵活、无模式的架构存储数据。与传统表不同,它使用文档和集合以一种类 JSON 的格式(称为 BSON)保存记录。该格式允许 MongoDB 以分层模型存储多种数据类型。

由于 MongoDB 没有固定模式,它支持任意类型的数据存储,是实时分析与数据流的理想选择。此外,现代应用常常会经历快速增长或不可预测的流量,MongoDB 对此尤为得心应手。例如,MongoDB 支持水平扩展,可通过增加服务器来应对不断增长的负载。

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 或更小的块

元数据存储

在 files 集合中存储文件的元数据

分块存储

在 chunks 集合中存储文件块

检索

从已存储的分块重建文件

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 可用的索引类型及其使用场景:

索引类型

说明

示例用例

单字段

对单个字段建立索引

为邮箱建立索引以加速查找

复合

对多个字段建立索引

按 lastName 和 age 排序

文本

对字符串字段进行全文搜索

通过关键词搜索博客文章

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 Maddula

作者

Srujana Maddula

Srujana 是一名自由职业技术写作者,拥有计算机科学四年制学位。她擅长撰写各类主题的内容,包括数据科学、云计算、开发、编程、安全等众多领域。她热爱经典文学,也喜欢探索新的旅行目的地。

主题