MongoDB 适用场景分析#
候选人小张在字节 P6 面试中,面试官问:
"你们公司什么场景用了 MongoDB?为什么?"
小张说:"我们用 MongoDB 存日志...因为 MongoDB 是文档数据库。"
面试官追问:"存日志为什么不用 Elasticsearch?"
小张说:"...也可以?"
面试官继续追问:"MongoDB 存日志有什么问题?"
小张答不上来了。
【面试官心理】 这道题我用来测试候选人对 MongoDB 适用场景的理解深度。能说出几个适用场景的占 50%,能讲清选型原因的占 20%,能对比其他方案的占 10%。
#一、适合 MongoDB 的场景 🔴
#1.1 内容管理系统(CMS)
// 场景:博客、新闻、电商商品等
// 特点:字段变化频繁,嵌套结构多
// 文章文档结构
{
_id: ObjectId(),
title: "MongoDB 最佳实践",
content: "...",
author: {
name: "张三",
bio: "MongoDB 专家",
social: {
twitter: "@zhang",
github: "zhangsan"
}
},
tags: ["MongoDB", "Database"],
comments: [
{
user: "李四",
text: "好文",
created_at: ISODate("2024-01-01")
}
],
related_articles: [
ObjectId("..."),
ObjectId("...")
]
}
// 为什么适合:
// 1. 字段随时增减,不需要 ALTER TABLE
// 2. 嵌套评论直接存储,减少 JOIN
// 3. 数组字段支持原子操作#1.2 用户画像与行为数据
// 场景:用户标签、行为记录、偏好设置
// 特点:字段不固定,数据量大
// 用户画像文档
{
_id: ObjectId("user_10001"),
user_id: 10001,
profile: {
age: 25,
gender: "male",
location: "Beijing"
},
tags: ["tech", "gaming", "music"],
behavior: {
page_views: 1500,
avg_session_time: 300,
last_active: ISODate("2024-01-15")
},
preferences: {
color: "dark",
language: "zh-CN"
},
// 随时可以添加新字段
subscription_tier: "premium"
}
// 为什么适合:
// 1. 灵活的数据模型,适应变化
// 2. 高并发写入
// 3. 支持多键索引#1.3 物联网(IoT)数据
// 场景:传感器数据、设备状态、日志
// 特点:时序数据、高写入量
// 设备数据文档
{
_id: ObjectId(),
device_id: "sensor_001",
timestamp: ISODate("2024-01-15T10:30:00Z"),
type: "temperature",
value: 25.5,
unit: "celsius",
location: {
building: "A",
floor: 3,
room: "301"
}
}
// 时序集合(MongoDB 5.0+)
db.createCollection("sensor_data", {
timeseries: {
timeField: "timestamp",
metaField: "metadata",
granularity: "seconds"
}
})
// 为什么适合:
// 1. 时序数据支持(5.0+)
// 2. 高写入吞吐量
// 3. 按时间范围查询高效#二、不适合 MongoDB 的场景 🟡
#2.1 金融交易系统
// ❌ 问题:强一致性要求
// MongoDB 事务比 MySQL 开销大
// 不适合的场景:
// - 账户余额扣减
// - 订单金额计算
// - 库存扣减
// 解决方案:使用 PostgreSQL 或 MySQL#2.2 复杂报表与BI分析
// ❌ 问题:复杂 SQL 支持有限
// MongoDB Aggregation Pipeline 学习曲线陡
// 不适合的场景:
// - 多表关联的大数据分析
// - 窗口函数查询
// - 复杂子查询
// 解决方案:使用 ClickHouse 或 PostgreSQL#2.3 日志存储与分析
// ❌ 问题:不是最优选择
// Elasticsearch 是更好的日志分析方案
// MongoDB 存日志的问题:
// 1. 全文检索能力弱
// 2. 日志聚合分析不如 ES
// 3. 磁盘占用大
// 解决方案:使用 ELK Stack (Elasticsearch + Logstash + Kibana)#三、真实业务场景案例 🟡
#3.1 电商订单系统
// MongoDB 适合存订单吗?
// 适合的场景:
// - 订单扩展字段多
// - 订单商品嵌套
// - 高并发写入
// 不适合的场景:
// - 需要强一致性
// - 需要复杂事务
// - 需要多表关联查询
// 混合方案:
// MySQL: 订单主表、支付记录、库存
// MongoDB: 订单详情、商品快照// MongoDB 订单文档
{
_id: ObjectId(),
order_no: "OR202401010001",
user_id: 10001,
status: "pending",
items: [
{
product_id: "P001",
product_name: "iPhone 15",
sku_id: "SKU001",
quantity: 1,
price: 7999.00
}
],
shipping_address: {
name: "张三",
phone: "13800138000",
address: "北京市朝阳区..."
},
// 扩展字段,随时添加
source: "app",
coupon_code: "SAVE10"
}#3.2 实时聊天系统
// MongoDB 适合存聊天记录吗?
// ✅ 适合的原因:
// 1. 消息嵌套结构
// 2. 高并发写入
// 3. 支持按时间范围查询
// 4. 副本集保证高可用
// 聊天消息文档
{
_id: ObjectId(),
conversation_id: ObjectId("..."),
sender_id: 10001,
receiver_id: 10002,
type: "text", // text/image/file/audio
content: "你好",
attachments: [
{ type: "image", url: "https://..." }
],
status: "sent", // sent/delivered/read
created_at: ISODate()
}
// 按会话查询
db.messages.find({
conversation_id: ObjectId("...")
}).sort({created_at: -1})#3.3 游戏后端数据
// 游戏数据为什么适合 MongoDB?
// 1. 玩家数据灵活
{
_id: ObjectId(),
player_id: 10001,
name: "玩家张三",
level: 50,
inventory: {
gold: 10000,
gems: 500,
items: [
{ item_id: "sword", count: 1 }
]
},
achievements: ["first_blood", "dragon_slayer"],
// 随时可以加新字段
vip_level: 3
}
// 2. 排行榜
db.players.createIndex({ score: -1 })
db.players.find().sort({ score: -1 }).limit(100)
// 3. 游戏日志
{
event: "item_purchase",
player_id: 10001,
item_id: "sword",
timestamp: ISODate()
}#四、选型 Checklist 🟡
#4.1 选择 MongoDB 的条件
// ✅ 选择 MongoDB 当:
// 1. 数据结构灵活多变
// 2. 需要频繁添加/删除字段
// 3. 写入量大于查询复杂度
// 4. 需要水平扩展
// 5. 文档天然建模(嵌套结构)
// 6. 需要高可用(副本集)#4.2 不选择 MongoDB 的条件
// ❌ 不选择 MongoDB 当:
// 1. 需要强 ACID 事务
// 2. 需要复杂多表 JOIN
// 3. 需要完整的 SQL 支持
// 4. 数据量小(< 1TB)
// 5. 团队不熟悉 NoSQL
// 6. 需要专业 BI 工具支持#4.3 常见组合方案
| 场景 | 数据库组合 | 说明 |
|---|---|---|
| 电商平台 | MySQL + Redis + MongoDB | MySQL 订单,Redis 缓存,MongoDB 商品详情 |
| 游戏 | MongoDB + MySQL | MongoDB 玩家数据,MySQL 充值记录 |
| 社交 | MongoDB + MySQL + Redis | MongoDB 动态,MySQL 用户,Redis Feed |
| IoT | MongoDB + TimescaleDB | MongoDB 设备元数据,TimescaleDB 时序数据 |
💡
MongoDB 不是 MySQL 的替代品,而是补充。选择时要根据具体业务需求,而不是"哪个更流行"。
【面试官心理】 能说出"日志存 Elasticsearch 更合适"和"金融系统不适合 MongoDB"的候选人,基本都有实际的架构经验。这是 P6+ 的水准。