MongoDB 入土刷题集

73次阅读
没有评论

共计 5258 个字符,预计需要花费 14 分钟才能阅读完成。

🟢 一、初级(基础概念与 CRUD)

1. MongoDB 是什么类型的数据库?

答案 :MongoDB 是一个 面向文档的 NoSQL 数据库,使用 BSON(Binary JSON)格式存储数据。

解析 :与传统关系型数据库(如 MySQL)不同,MongoDB 不使用表和行,而是使用 集合(Collection)文档(Document)。文档是键值对的集合,结构灵活,支持嵌套。


2. MongoDB 中的“集合”(Collection)相当于关系型数据库中的什么?

答案 :相当于 表(Table)

解析 :集合是文档的容器,类似于关系型数据库中的表。但集合中的文档 不要求具有相同的结构(schema-less)。


3. 如何在 MongoDB 中创建一个数据库?

答案:使用 use <database_name> 命令。如果数据库不存在,MongoDB 会在首次插入数据时自动创建它。

示例

use mydb
db.myCollection.insertOne({name: "Alice"})

此时 mydb 数据库被真正创建。


4. 如何查看当前所有数据库?

答案show dbs

注意:刚 use 一个新数据库但未插入数据时,show dbs 不会显示它。


5. 插入一条文档到集合 users 中,字段为 {name: "Tom", age: 25}

答案

db.users.insertOne({name: "Tom", age: 25})

解析insertOne() 插入单个文档;也可用 insertMany() 插入多个。


6. 查询 users 集合中所有文档。

答案

db.users.find()

或格式化输出:

db.users.find().pretty()

7. 查询 usersage 大于 20 的用户。

答案

db.users.find({age: { $gt: 20} })

解析$gt 是比较操作符,表示“大于”。


8. 更新 usersname 为 “Tom” 的用户,将其 age 改为 26。

答案

db.users.updateOne({name: "Tom"}, {$set: { age: 26} })

注意 :必须使用 $set,否则会 替换整个文档


9. 删除 usersage 小于 18 的所有用户。

答案

db.users.deleteMany({age: { $lt: 18} })

10. MongoDB 文档的主键字段叫什么?由谁生成?

答案:字段名为 _id,默认由 MongoDB 自动生成一个 ObjectId(12 字节唯一标识)。

解析_id 是唯一索引,不可重复。用户也可自定义 _id 值(如字符串、数字等)。


11. ObjectId 由哪几部分组成?

答案:共 12 字节,包含:

  • 4 字节:时间戳(秒)
  • 3 字节:机器标识
  • 2 字节:进程 ID
  • 3 字节:计数器

用途:可从 ObjectId 反推文档创建时间。


12. 如何查看集合 users 的索引?

答案

db.users.getIndexes()

13. 如何为 users 集合的 name 字段创建索引?

答案

db.users.createIndex({name: 1})

1 表示升序,-1 表示降序。


14. MongoDB 默认是否区分大小写进行字符串查询?

答案 ,默认区分大小写。

示例{name: "alice"} 不会匹配 "Alice"

解决:使用正则表达式或文本索引实现不区分大小写。


15. 如何退出 MongoDB Shell?

答案:输入 exit 或按 Ctrl + D


🟡 二、中级(查询进阶、聚合、索引、数据建模)

16. 使用聚合管道(Aggregation Pipeline)统计 users 中每个年龄段的人数。

答案

db.users.aggregate([
  {$group: { _id: "$age", count: { $sum: 1} } }
])

解析$groupage 分组,$sum: 1 表示每条文档计数 1。


17. 如何查询嵌套文档?例如文档为 {name: "Bob", address: { city: "Beijing"} },查询北京用户。

答案

db.users.find({"address.city": "Beijing"})

注意:嵌套字段需用点号 . 引用。


18. 如何查询数组字段包含特定值?例如 tags: ["news", "tech"],查询包含 “tech” 的文档。

答案

db.articles.find({tags: "tech"})

或使用 $in

db.articles.find({tags: { $in: ["tech"] } })

19. $lookup 在聚合中有什么作用?

答案 :实现 左外连接(left outer join),用于关联两个集合。

示例:将 orderscustomers 关联:

db.orders.aggregate([
  {
    $lookup: {
      from: "customers",
      localField: "customerId",
      foreignField: "_id",
      as: "customerInfo"
    }
  }
])

20. 什么是复合索引?何时使用?

答案:对多个字段创建的索引,如 {name: 1, age: -1}

使用场景:当查询条件包含多个字段时,复合索引可大幅提升性能。

注意 :遵循 最左前缀原则


21. 解释 db.collection.explain("executionStats") 的作用。

答案:显示查询的执行计划和性能统计,包括:

  • 是否使用索引(IXSCAN vs COLLSCAN
  • 扫描文档数(totalDocsExamined
  • 返回文档数(nReturned

用途:用于查询优化。


22. 什么是“覆盖查询”(Covered Query)?

答案 :查询所需的所有字段都包含在索引中,MongoDB 无需回表读取文档,直接从索引返回结果。

示例

// 索引:{name: 1, age: 1}
db.users.find({name: "Tom"}, {_id: 0, name: 1, age: 1})

此查询是覆盖查询。


23. 如何限制查询结果数量?如只取前 5 条。

答案

db.users.find().limit(5)

24. 如何跳过前 10 条结果,用于分页?

答案

db.users.find().skip(10).limit(10)

注意 skip + limit 在大数据量下性能差,建议用 基于游标的分页(如 _id > lastId)。


25. 什么是 TTL 索引?如何创建?

答案:TTL(Time-To-Live)索引可自动删除过期文档,常用于日志、会话管理。

创建

db.logs.createIndex({createdAt: 1}, {expireAfterSeconds: 3600})

文档在 createdAt 时间后 1 小时自动删除。


26. 解释 $unwind 聚合阶段的作用。

答案:将数组字段“展开”为多条文档。

示例

// 原文档:{_id: 1, items: ["A", "B"] }
db.orders.aggregate([{ $unwind: "$items"}])
// 输出两条:{_id:1, items:"A"}, {_id:1, items:"B"}

27. 如何在更新时“upsert”(不存在则插入)?

答案:在 updateOneupdateMany 中设置 upsert: true

db.users.updateOne({ name: "NewUser"},
  {$set: { age: 30} },
  {upsert: true}
)

28. 什么是“原子性”?MongoDB 的写操作是否原子?

答案 :MongoDB 单文档写操作是原子的,但跨文档操作不是。

建议:通过嵌入文档或事务(4.0+)保证多文档一致性。


29. 如何查看 MongoDB 版本?

答案

db.version()

或 shell 启动时显示。


30. 解释 mongodmongo 的区别。

答案

  • mongod:MongoDB 数据库服务进程(daemon)
  • mongo(旧)或 mongosh(新):客户端 Shell 工具

🔴 三、高级(事务、分片、复制、性能调优、安全)

31. MongoDB 从哪个版本开始支持多文档事务?

答案 4.0 版本(仅限副本集),4.2 版本 扩展到分片集群。

注意:事务有性能开销,应谨慎使用。


32. 如何在 MongoDB 中开启一个事务?

答案(Node.js 示例):

const session = client.startSession();
try {await session.withTransaction(async () => {await db.users.updateOne({ _id: 1}, {$inc: { balance: -100} }, {session});
    await db.users.updateOne({_id: 2}, {$inc: { balance: 100} }, {session});
  });
} finally {await session.endSession();
}

33. 什么是副本集(Replica Set)?作用是什么?

答案 :副本集是一组维护 相同数据集 的 MongoDB 实例,提供:

  • 高可用(自动故障转移)
  • 数据冗余
  • 读扩展(可从 secondary 读)

组成:1 个 Primary + 多个 Secondary +(可选)Arbiter。


34. 什么是分片(Sharding)?何时需要分片?

答案 :分片是将数据 水平拆分 到多个服务器(shard)的技术。

适用场景

  • 数据量 > 单机存储容量
  • 写入吞吐量 > 单机处理能力

组件:Shard、Config Server、Mongos(路由)。


35. 如何选择分片键(Shard Key)?

答案:好的分片键应满足:

  • 高基数(值多样)
  • 高写分布(避免热点)
  • 查询常用(避免 scatter-gather)

避免:单调递增字段(如 ObjectId、时间戳)作为分片键。


36. 解释“读偏好”(Read Preference)。

答案:控制客户端从副本集的哪个节点读取数据:

  • primary(默认)
  • primaryPreferred
  • secondary
  • secondaryPreferred
  • nearest

用途:负载均衡、降低主节点压力。


37. 什么是“写关注”(Write Concern)?

答案:控制写操作的确认级别,例如:

{w: 1}        // 默认,主节点确认
{w: "majority"} // 大多数副本确认
{j: true}     // 写入日志(journal)

权衡:更高的写关注 = 更强一致性,但更低性能。


38. 如何备份 MongoDB 数据?

答案:常用方法:

  • mongodump / mongorestore(逻辑备份)
  • 文件系统快照(需启用 journal)
  • Ops Manager / Cloud Manager(企业级)

示例

mongodump --db mydb --out /backup/

39. 什么是“oplog”?它在副本集中起什么作用?

答案 :oplog(operations log)是一个 固定集合,记录所有数据修改操作。

作用 :Secondary 节点通过 复制 oplog 来同步 Primary 的数据变更。


40. 如何监控 MongoDB 性能?

答案:工具包括:

  • db.currentOp():查看当前操作
  • db.killOp():终止慢查询
  • MongoDB Atlas / Ops Manager(可视化)
  • Prometheus + MongoDB Exporter

41. 解释“存储引擎”(Storage Engine)。MongoDB 默认使用哪个?

答案:存储引擎管理数据在磁盘上的存储方式。

  • WiredTiger(默认,3.2+):支持文档级并发、压缩、事务
  • MMAPv1(旧版,已弃用)

42. 如何启用 MongoDB 认证(Authentication)?

答案

  1. 启动 mongod 时添加 --auth
  2. 创建管理员用户:
   use admin
   db.createUser({user: "admin", pwd: "123456", roles: ["root"] })
  1. 客户端连接时使用 -u -p 参数。

43. 什么是“角色”(Role)?列举几个内置角色。

答案:角色定义用户权限。内置角色包括:

  • read / readWrite(数据库级)
  • dbAdmin(管理集合)
  • userAdmin(管理用户)
  • root(超级用户)

44. 如何优化一个慢查询?

答案:步骤:

  1. 使用 explain("executionStats") 分析
  2. 检查是否全表扫描(COLLSCAN)
  3. 为查询字段添加合适索引
  4. 避免 $where$regex(非前缀)
  5. 考虑数据模型重构(如嵌入 vs 引用)

45. MongoDB 是否支持 JOIN?如何实现多表关联?

答案 :MongoDB 不支持 SQL 式 JOIN,但可通过以下方式实现关联:

  • 嵌入文档(Embedding):适合一对少、数据不常变
  • 引用 ID(Referencing)+ 应用层多次查询
  • 聚合 $lookup:适合偶尔关联,性能低于嵌入

原则 以读写模式驱动数据建模,而非范式。


✅ 总结

难度 题数 覆盖知识点
初级 15 基础概念、CRUD、索引、ObjectId
中级 15 聚合、嵌套查询、复合索引、分页、TTL、upsert
高级 15 事务、副本集、分片、安全、性能调优、备份

💡 建议

  • 初学者先掌握初级 + 中级
  • 面试 / 生产环境需重点掌握高级部分(尤其事务、分片、性能)
  • 动手实践:使用 MongoDB Atlas 免费集群练习

正文完
 0
一诺
版权声明:本站原创文章,由 一诺 于2025-10-10发表,共计5258字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码