MongoDB文档模型设计指南


MongoDB文档模型设计指南

MongoDB作为文档型数据库,其数据模型设计与传统关系型数据库有很大不同。合理的数据模型设计直接影响到查询性能、数据一致性和开发效率。本文将介绍MongoDB文档模型设计的核心原则和最佳实践。

一、嵌入 vs 引用

这是MongoDB数据模型设计中最核心的决策:

// 嵌入文档 - 适合一对一和少量一对多关系
// 优点:一次查询获取所有数据,无需JOIN
{
  _id: ObjectId("..."),
  name: "张三",
  address: {
    city: "北京",
    street: "中关村大街1号",
    zipCode: "100080"
  },
  contacts: [
    { type: "phone", value: "13800138000" },
    { type: "email", value: "zhangsan@example.com" }
  ]
}

// 引用文档 - 适合多对多和大量一对多关系
{
  _id: ObjectId("..."),
  orderNo: "ORD20240101001",
  userId: ObjectId("..."),    // 引用用户ID
  items: [
    { productId: ObjectId("..."), quantity: 2, price: 99.9 }
  ]
}

二、常见模式设计

// 模式1:属性模式 - 处理动态属性
{
  name: "笔记本电脑",
  attrs: [
    { k: "品牌", v: "联想" },
    { k: "内存", v: "16GB" },
    { k: "CPU", v: "i7-13700H" }
  ]
}
// 建立索引
db.products.createIndex({ "attrs.k": 1, "attrs.v": 1 })

// 模式2:桶模式 - 时序数据
{
  sensorId: "TEMP_001",
  date: ISODate("2024-01-01"),
  readings: [
    { time: "00:00", value: 22.5 },
    { time: "01:00", value: 22.3 }
  ],
  min: 20.1,
  max: 25.8,
  avg: 22.8
}

// 模式3:多态模式
{
  _id: ObjectId("..."),
  type: "book",
  title: "MongoDB权威指南",
  author: "Kristina Chodorow",
  pages: 432
}
{
  _id: ObjectId("..."),
  type: "electronics",
  name: "无线鼠标",
  brand: "罗技",
  warranty: 12
}

三、索引优化

// ESR原则:Equal, Sort, Range
// 精确匹配 → 排序 → 范围查询

// 查询:{ status: "active" }.sort({ createdAt: -1 }).limit(20)
// 最佳索引:
db.orders.createIndex({ status: 1, createdAt: -1 })

// 复合索引
db.users.createIndex({ city: 1, age: -1, name: 1 })

// 文本索引
db.articles.createIndex({ title: "text", content: "text" })
db.articles.find({ text: { search: "MongoDB 性能" } })

// TTL索引 - 自动过期
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

// 部分索引 - 减少索引大小
db.orders.createIndex(
  { status: 1, createdAt: -1 },
  { partialFilterExpression: { status: "active" } }
)

四、聚合管道

// 统计每月销售额
db.orders.aggregate([
  { match: { status: "completed", createdAt: { gte: ISODate("2024-01-01") } } },
  { group: {
    _id: { dateToString: { format: "%Y-%m", date: "$createdAt" } },
    totalSales: { sum: "$amount" },
    orderCount: { sum: 1 },
    avgOrder: { avg: "$amount" }
  }},
  { sort: { _id: 1 } }
])

MongoDB的文档模型给了开发者极大的灵活性,但也带来了更大的设计责任。核心原则是:根据应用的查询模式来设计数据模型,让最频繁的查询最高效。切忌简单地将关系型数据库的表直接搬运为MongoDB的集合。


0.049563s