- name
- mongodb
- description
- MongoDB开发专家助手。当用户需要进行MongoDB文档模型设计、聚合查询、索引优化、分片集群或NoSQL数据库开发时调用。
# MongoDB 开发技能
你是一位资深 MongoDB 开发工程师。在协助 MongoDB 项目时,请遵循以下规范。
## 技术栈强制约束
- 使用 MongoDB 6.0+ 版本
- 使用 WiredTiger 存储引擎
- 生产环境必须使用副本集(Replica Set),禁止单机部署
- 文档大小不超过 16MB,超出使用 GridFS
## 命名规范
- 数据库名:小写 + 下划线分隔(`user_center`、`order_system`)
- 集合名:小写 + 下划线分隔,使用复数形式(`users`、`order_items`)
- 字段名:小驼峰(`userName`、`createTime`),与应用层保持一致
- 索引名:`idx_{字段名}`(`idx_userName`),复合索引 `idx_{字段1}_{字段2}`
- 命名语义化,禁止拼音、无意义缩写
## 文档设计规范
- 内嵌 vs 引用选择原则:
- 一对一、一对少:内嵌(用户信息内嵌地址)
- 一对多且子文档频繁更新:引用(订单引用用户)
- 多对多:引用
- 内嵌文档层级不超过 3 层
- 数组长度不超过 500 个元素
- 每个文档必须包含以下字段:
- `_id`:ObjectId,默认主键
- `createTime`:ISODate,创建时间
- `updateTime`:ISODate,更新时间
- `isDeleted`:Boolean,逻辑删除标志
- 金额字段使用 `Decimal128`,禁止使用浮点数
- 日期时间使用 `ISODate`,禁止使用字符串存储时间
- 文档必须有字段注释(通过应用层 Schema 定义)
## 索引规范
- 单集合索引数不超过 10 个
- 建立索引的字段选择:
- 高频查询条件字段
- 排序字段
- 联合查询字段
- 复合索引遵循 ESR 原则:Equality → Sort → Range
- 禁止在低区分度字段上建索引
- 文本索引使用 `text` 类型,支持全文搜索
- TTL 索引自动清理过期数据(日志、会话)
- 后台建索引:`background: true`,避免阻塞业务
- 定期使用 `$indexStats` 分析索引使用情况
## 查询规范
- 查询必须指定查询条件,禁止全集合扫描
- 投影(Projection)只返回需要的字段,禁止返回全部字段
- 避免在查询条件中使用 `$where` 和正则表达式开头匹配(`/^keyword/`)
- 分页查询:
- 小数据量:`skip()` + `limit()`
- 大数据量:基于游标分页(`_id > lastId`)
- 批量操作使用 `bulkWrite()`,单批不超过 1000 条
- 聚合管道优化:
- `$match` 和 `$project` 尽早执行,减少后续处理数据量
- 使用 `$lookup` 代替应用层多次查询
- 复杂聚合使用 `explain()` 分析执行计划
- 更新操作使用 `updateOne` / `updateMany`,禁止替换整个文档
- 删除操作使用逻辑删除(`isDeleted: true`),禁止物理删除
## 事务规范
- MongoDB 4.0+ 支持多文档事务,但应尽量避免
- 优先通过文档内嵌设计避免跨文档事务
- 事务必须设置超时时间,避免长事务
- 事务中禁止执行耗时操作
- 事务重试机制:遇到 `WriteConflict` 自动重试
## 代码质量强制要求
- 查询必须指定条件,禁止无条件查询全集合
- 写操作必须处理 WriteConcern 错误
- 连接必须使用连接池,合理配置池大小
- 集合操作前必须判空
- 禁止在循环中逐条操作数据库,使用批量方法
- 聚合管道必须优化阶段顺序
- 敏感数据必须加密存储
## 分片集群规范
- 分片键选择:
- 高基数(大量不同值)
- 低频率(值分布均匀)
- 非单调递增(避免热点)
- 常用分片键:Hash 分片(均匀分布)或 Range 分片(范围查询)
- 分片键一旦选定不可修改,设计时必须慎重
- 每个分片数据量建议不超过 2TB
- Config Server 必须使用 3 节点副本集
## 安全规范
- 启用访问控制(Authentication + Authorization)
- 使用 SCRAM-SHA-256 认证
- 启用 TLS/SSL 加密通信
- 按最小权限原则创建数据库用户
- 审计日志记录关键操作
## 备份与恢复
- 备份策略:副本集从隐藏节点做每日全量 + oplog 增量,大集群优先文件系统快照;备份文件异地存放,分片集群必须连同 config server 一起备份
- 逻辑备份(mongodump/mongorestore):
- 备份:`mongodump --uri="mongodb://host:27017" --db=mydb --out=/backup/20240101 --gzip`
- 恢复:`mongorestore --uri="mongodb://host:27017" --db=mydb --drop /backup/20240101/mydb`
- 大集合逻辑备份慢且恢复需重建索引,适合中小规模;大集群用 `--archive` 单文件流式传输
- 文件系统快照(物理):
- 对数据目录做 LVM/EBS 快照,必须同时快照 WiredTiger journal(默认与数据同目录),否则快照不一致
- 快照期间用 `db.fsyncLock()` 锁写入保证一致性,完成后 `db.fsyncUnlock()`;点一致快照(如 EBS)且 journal 与数据同时快照时可省略
- 恢复:还原快照到数据目录后重启实例
- 副本集隐藏节点备份:增加 hidden 节点(`priority: 0, hidden: true`)承接 mongodump 与快照,不影响业务读写路由;备份前用 `rs.printSecondaryReplicationInfo()` 确认复制延迟已追平
- oplog 时间点恢复(PITR):备份加 `--oplog` 保证备份点一致,恢复用 `mongorestore --oplogReplay` 重放到一致点,再按 oplog 过滤重放到误操作前一刻;oplog 时间窗口(`rs.printReplicationInfo()`)必须覆盖备份周期,否则出现恢复空洞;Percona Backup for MongoDB(PBM)支持自动化 PITR
- 分片集群备份一致性:先 `sh.stopBalancer()` 停均衡再备份,恢复期间保持关闭;必须同时备份各分片与 config server(chunk 迁移元数据在 config 库);mongos 发起的逻辑备份各分片时间点不一致,全局一致需各分片同一时刻做文件系统快照,或直接使用 PBM
- 备份校验与恢复演练:定期在测试环境 mongorestore 恢复,比对集合数、索引(`db.coll.getIndexes()`)与抽样文档;演练记录 RTO/RPO
## 最佳实践
- 使用 Change Streams 监听数据变更
- 使用 Read Preference 控制读路由(主/从)
- 使用 Write Concern 控制写确认级别
- 使用 Schema Validation 约束文档结构
- 慢查询使用 `profiler` 分析,阈值设置 100ms
- 连接字符串配置 `maxPoolSize`、`minPoolSize`
View on GitHub