Skip to content
Charles
Go back

MongoDB 也可以做很多事

Edit page

引言

“一个数据库解决所有问题”听起来很诱人,但 MongoDB 的正确答案不是复制 PostgreSQL 的用法,而是利用文档模型解决文档型问题。

MongoDB 把记录保存为 BSON 文档。一个业务对象的字段、嵌套对象和数组可以一起读取和更新,特别适合产品目录、内容管理、用户配置、设备状态和事件元数据这类结构变化较快的数据。

本文延续 PostgreSQL for EverythingSQLite for Everything 的取舍方式:先减少不必要的系统,但不把 MongoDB 包装成关系数据库的替代品。

MongoDB 能把文档、搜索、时间序列、变更通知、短期数据和一部分图查询放在同一个平台里。真正值得讨论的不是“MongoDB 能不能做”,而是“这种做法是否让数据模型和运维更简单”。

稳定可靠

MongoDB 已经从早期的灵活文档存储发展成成熟的副本集和分片数据库。副本集、写关注级别、索引和事务让它可以承担正式业务;文档模型则保留了内容结构快速变化的优势。

灵活 schema 不等于无 schema。生产系统仍然需要字段约定、类型校验、索引和数据生命周期,否则“灵活”很快会变成同一个字段有五种类型。

易于运行、安装和扩展

本地可以运行 MongoDB Community,线上可以使用 Atlas 或其他托管方案。副本集和分片提供了从单节点开发到高可用、水平扩展的路径,但分片键、热点、索引和容量规划不能等到数据量上来后再猜。

托管服务减少了安装工作,不会自动替你解决 schema、慢查询、备份恢复和成本控制。MongoDB 的能力越多,越需要明确哪些能力真正属于当前系统。

简化 IT 架构

MongoDB 的文档模型让业务对象、嵌套数据和数组一起存取,再把搜索、事件、时间序列和 TTL 能力放在同一个数据平台里。

MongoDB 可以替代 Solr 和 Elastic:全文检索

MongoDB 生态可以提供全文搜索能力,适合希望让业务文档、过滤条件和检索结果靠近同一数据平台的项目。选择前要确认部署形态、版本、索引构建时间、数据规模和费用,不能把“有一个搜索接口”理解成自动拥有搜索引擎的全部能力。

MongoDB 可以替代传统文档服务:JSON 和 BSON 文档

MongoDB 没有要求所有文档必须拥有完全相同的字段,但“灵活 schema”不代表“没有 schema”。字段命名、类型、嵌套层级和数组大小仍然应该由应用约定,关键字段可以用校验规则保护。

例如商品的规格可能因品类不同而变化:

db.products.insertOne({
  name: "机械键盘",
  category: "keyboard",
  price: NumberDecimal("399.00"),
  attributes: {
    layout: "75%",
    wireless: true,
    switches: ["linear", "tactile"]
  },
  updatedAt: new Date()
});

db.products.createIndex({ category: 1, "attributes.wireless": 1 });

db.products.find({
  category: "keyboard",
  "attributes.wireless": true
});

把经常一起读取的字段嵌入同一个文档,可以减少关联查询。需要独立生命周期、无限增长或被多个对象共享的数据,不要盲目嵌入;这类数据适合单独集合并使用引用。

MongoDB 可以替代 Kafka 和 RabbitMQ:Change Streams

如果订单写入后需要通知搜索索引、缓存刷新或外部同步,可以订阅 Change Streams:

const changes = db.orders.watch([
  { $match: { operationType: { $in: ["insert", "update"] } } }
]);

for await (const change of changes) {
  console.log(change.operationType, change.documentKey);
}

Change Streams 更适合低吞吐的变更通知和事件扇出,不能直接当成 Kafka 或 RabbitMQ 的通用消息队列。消费者要保存 resume token,并处理重连、重复事件和下游幂等。Change Streams 依赖副本集或分片集群,时序集合不支持 Change Streams,时序数据如果需要变更通知,应写入普通集合或设计独立同步链路。

MongoDB 可以替代 ClickHouse:时间序列数据

设备监控、应用指标、传感器采样等场景可以使用 MongoDB 的 time series collections。它会根据时间和元数据组织采样数据,查询时仍然可以使用 MongoDB 的查询接口。

短期数据则可以使用 TTL 索引自动清理:

db.sessions.createIndex(
  { expiresAt: 1 },
  { expireAfterSeconds: 0 }
);

db.sessions.insertOne({
  userId: "u_42",
  expiresAt: new Date(Date.now() + 30 * 60 * 1000)
});

TTL 清理是后台行为,不应该拿它当作精确到秒的业务计时器。需要严格时间语义的订单、账务和权限逻辑,仍然由业务代码和事务明确处理。

MongoDB 生态可以提供向量搜索能力,适合希望让业务文档、过滤条件和检索结果靠近同一数据平台的 AI 工作流。选择前要确认部署形态、版本、索引构建时间、向量规模、召回要求和费用。小规模检索可以减少一个专用向量数据库,大规模高并发场景仍应单独评估专用系统。

MongoDB 可以替代 Redis:TTL 和临时缓存

会话、验证码、临时令牌和短期结果可以使用 TTL 索引自动清理。需要高命中率、复杂淘汰策略和极低延迟时,Redis 仍然更合适;MongoDB 的优势是临时数据和业务文档可以共享权限、备份和查询方式。

MongoDB 可以替代文件系统:GridFS

文件也可以使用 GridFS 拆分保存,但图片、视频和备份文件通常更适合对象存储。MongoDB 里保存文件元数据、权限和对象地址,业务查询更清楚,成本也更容易控制。

MongoDB 可以替代图数据库:$graphLookup

组织树、分类树和有限深度的关系查询可以通过 $graphLookup 实现,不必单独部署图数据库。需要复杂图算法、任意方向高频遍历或图分析平台时,专用图数据库会更自然。

MongoDB 作为 GraphDB 和 Neo4J 的替代方案

$graphLookup 适合有限深度的树形和关系遍历,但 MongoDB 不应被当成完整的图数据库。需要复杂图算法、任意方向高频遍历或图分析平台时,仍应选择专用图数据库。

MongoDB 可以替代微服务

MongoDB 的聚合管道可以在数据库内完成过滤、展开数组、分组和排序,直接输出接口所需的文档结构:

db.orders.aggregate([
  { $match: { status: "paid" } },
  { $unwind: "$items" },
  {
    $group: {
      _id: "$items.productId",
      quantity: { $sum: "$items.quantity" },
      amount: { $sum: { $multiply: ["$items.price", "$items.quantity"] } }
    }
  },
  { $sort: { amount: -1 } }
]);

聚合管道可以直接输出接口所需的文档结构,Change Streams 可以把数据变化交给下游消费者。这样可以减少一层只负责拼 JSON 或手工同步的服务,但认证、业务规则和跨系统事务仍然需要应用层处理。

MongoDB 不能替代 PlayStation 5

把数据库查询写成游戏只是展示表达能力的玩笑。实际选型应该看文档边界、查询模式和运维成本。

结论

MongoDB 支持多文档事务,但事务会增加协调成本。最好的第一选择仍然是让一次业务操作尽量落在一个文档内;只有确实需要跨文档原子性时,才使用事务。

下列情况要谨慎选 MongoDB:

  1. 核心数据有大量强外键关系和复杂多表报表。
  2. 业务依赖数据库层面的严格约束,而不是应用层 schema 校验。
  3. 数据结构其实非常稳定,查询主要是关系连接和聚合。
  4. 团队更熟悉 SQL,却没有 MongoDB 数据建模和索引管理经验。

这不代表 MongoDB 不能做这些事,而是做出来的模型可能比 PostgreSQL 更绕。数据库的优势必须和数据形状匹配,不能只看某个产品的功能列表。

MongoDB 的核心能力是“把一个业务对象作为一个文档来读写”,然后在此基础上提供聚合、时间序列、TTL、变更流和搜索能力。它适合文档边界清楚、字段变化快、读写模式围绕对象展开的系统。

如果数据本质上是订单、账户、库存之间的关系网络,优先使用关系数据库;如果数据本质上是内容、配置、目录或事件文档,MongoDB 才更可能让模型变简单。

官方资料:文档模型schema 设计Change Streams时间序列集合限制schema 设计模式


Edit page
Share this post:

Previous Post
MySQL 也可以做很多事
Next Post
Go 数据库迁移方案对比