MongoDB的数据模型(文档、集合、数据库)
MongoDB的数据模型(文档、集合、数据库)
MongoDB作为NoSQL数据库的代表,采用灵活的文档数据模型,核心概念包括文档、集合和数据库。这种设计让MongoDB能够高效处理非结构化或半结构化数据,同时保持强大的查询能力。
文档(Document)
文档是MongoDB中最基本的数据单元,采用BSON(Binary JSON)格式存储。每个文档由键值对组成,类似于JSON对象,但支持更丰富的数据类型。
// 一个典型的MongoDB文档示例
{
_id: ObjectId("507f1f77bcf86cd799439011"),
name: "张三",
age: 28,
address: {
city: "北京",
district: "海淀区"
},
hobbies: ["编程", "游泳", "摄影"],
createdAt: new Date("2023-01-15")
}
文档的特点包括:
_id
字段是文档的唯一标识符,如果不指定会自动生成- 支持嵌套文档(如address字段)
- 可以存储数组(如hobbies字段)
- 字段值可以是多种数据类型(字符串、数字、日期等)
文档大小限制为16MB,适合存储大多数业务数据。对于更大的文件,MongoDB提供了GridFS规范。
集合(Collection)
集合是一组文档的容器,类似于关系型数据库中的表,但没有固定的表结构。
// 用户集合中的不同文档结构示例
[
{
_id: 1,
username: "user1",
email: "user1@example.com"
},
{
_id: 2,
username: "user2",
profile: {
firstName: "李",
lastName: "四"
},
lastLogin: ISODate("2023-05-20T08:30:00Z")
}
]
集合的重要特性:
- 动态模式:集合中的文档可以有不同的结构
- 命名规则:不能包含空字符、$符号等特殊字符
- 索引支持:可以在集合上创建索引提高查询性能
- 上限集合(Capped Collection):固定大小的集合,适合日志等场景
集合操作示例(使用MongoDB Shell):
// 创建集合
db.createCollection("users")
// 查看所有集合
show collections
// 删除集合
db.users.drop()
数据库(Database)
数据库是MongoDB中的顶级组织结构,包含多个集合。一个MongoDB实例可以承载多个数据库。
数据库的关键特点:
- 命名空间隔离:不同数据库中的集合可以同名
- 独立权限控制:可以为每个数据库设置不同的访问权限
- 存储配额:可以为数据库设置存储限制
常用数据库命令:
// 切换/创建数据库
use mydb
// 查看当前数据库
db
// 查看所有数据库
show dbs
// 删除当前数据库
db.dropDatabase()
数据模型设计模式
MongoDB提供了多种数据模型设计方法,常见的有:
- 内嵌文档模式:
// 订单与订单项内嵌
{
_id: "ORD123",
customer: "张三",
items: [
{ product: "手机", quantity: 1, price: 5999 },
{ product: "耳机", quantity: 2, price: 299 }
],
total: 6597
}
- 引用模式:
// 用户集合
{
_id: "USER1",
name: "李四"
}
// 订单集合
{
_id: "ORDER1",
user: "USER1", // 引用用户ID
amount: 1000
}
- 混合模式(内嵌+引用):
// 博客文章与评论
{
_id: "POST1",
title: "MongoDB指南",
content: "...",
recentComments: [ // 内嵌最近几条评论
{ user: "USER1", text: "好文章", date: ISODate(...) },
{ user: "USER2", text: "很有帮助", date: ISODate(...) }
],
commentCount: 15 // 总评论数
}
数据类型
MongoDB支持丰富的数据类型,包括:
- 基本类型:String、Integer、Boolean、Double
- 日期类型:Date、Timestamp
- 对象ID:ObjectId
- 二进制数据:BinData
- 特殊类型:Null、Regular Expression、JavaScript代码
- 地理空间类型:Point、LineString、Polygon
// 包含多种数据类型的文档
{
_id: ObjectId("5f8d8a7b2f4a1e3d6c9b8a7d"),
name: "示例文档",
count: 42,
active: true,
price: 19.99,
tags: ["mongodb", "database", "nosql"],
createdAt: new Date(),
location: {
type: "Point",
coordinates: [116.404, 39.915]
},
metadata: {
version: "1.0",
hash: BinData(0, "aGVsbG8gd29ybGQ=")
}
}
索引与数据模型
索引对数据模型设计有重要影响。MongoDB支持多种索引类型:
// 创建单字段索引
db.users.createIndex({ username: 1 })
// 创建复合索引
db.orders.createIndex({ customer: 1, date: -1 })
// 创建多键索引(数组字段)
db.products.createIndex({ tags: 1 })
// 创建文本索引
db.articles.createIndex({ content: "text" })
// 创建地理空间索引
db.places.createIndex({ location: "2dsphere" })
索引设计应考虑查询模式,避免过度索引导致写入性能下降。
数据模型最佳实践
- 根据查询模式设计文档结构:
// 优化读取性能的设计
{
_id: "PROD001",
name: "智能手机",
price: 2999,
inventory: {
warehouse1: 50,
warehouse2: 30
},
dailySales: [
{ date: ISODate("2023-05-01"), count: 12 },
{ date: ISODate("2023-05-02"), count: 8 }
]
}
- 处理一对多关系:
// 少量子文档:内嵌
{
orderId: "ORD1001",
items: [
{ product: "A", qty: 2 },
{ product: "B", qty: 1 }
]
}
// 大量子文档:引用
{
blogPostId: "POST100",
title: "...",
commentCount: 142,
recentComments: [...]
}
- 考虑文档增长:
// 预分配空间避免文档移动
{
_id: "USER100",
name: "王五",
activityLog: new Array(100).fill(null)
}
- 分片集群中的数据模型考虑:
// 选择合适的分片键
sh.shardCollection("mydb.orders", { customerId: 1, orderDate: 1 })
数据模型演进
MongoDB的无模式设计允许灵活演进数据模型:
// 添加新字段
db.products.updateMany(
{},
{ $set: { lastUpdated: new Date() } }
)
// 重命名字段
db.users.updateMany(
{},
{ $rename: { "oldField": "newField" } }
)
// 迁移数据格式
db.orders.aggregate([
{ $project: {
customerId: 1,
items: 1,
total: { $sum: "$items.price" }
}},
{ $out: "orders_new" }
])
性能考量
数据模型设计直接影响性能:
- 工作集大小:确保活跃数据能放入内存
- 文档大小:避免过大的文档(接近16MB限制)
- 索引覆盖:设计能被索引完全覆盖的查询
- 写入模式:考虑批量插入与更新效率
// 批量插入优化
db.products.insertMany([
{ name: "商品1", price: 10 },
{ name: "商品2", price: 20 },
// ...更多文档
])
// 批量更新优化
db.orders.updateMany(
{ status: "pending" },
{ $set: { status: "processed" } }
)
实际应用示例
电子商务平台的数据模型设计:
// 产品集合
{
_id: "P1001",
sku: "MBP-13-2023",
name: "MacBook Pro 13英寸 2023",
category: ["电子产品", "笔记本电脑"],
price: 12999,
attributes: {
cpu: "M2",
ram: "16GB",
storage: "512GB SSD"
},
inventory: 50,
ratings: [
{ userId: "U1001", score: 5, comment: "非常满意" },
{ userId: "U1002", score: 4 }
],
avgRating: 4.5
}
// 订单集合
{
_id: "O2001",
customerId: "U1001",
items: [
{ productId: "P1001", quantity: 1, price: 12999 },
{ productId: "P1002", quantity: 2, price: 199 }
],
shipping: {
address: "北京市朝阳区...",
method: "express"
},
payment: {
method: "credit_card",
transactionId: "TXN123456"
},
status: "completed",
createdAt: ISODate("2023-05-15T10:30:00Z"),
updatedAt: ISODate("2023-05-18T14:15:00Z")
}
高级数据模型技术
- 多态模式:
// 不同类型的事件文档
[
{
_id: "EVT001",
type: "login",
userId: "U1001",
timestamp: ISODate(...),
ipAddress: "192.168.1.1"
},
{
_id: "EVT002",
type: "purchase",
userId: "U1002",
timestamp: ISODate(...),
orderId: "O2001",
amount: 12999
}
]
- 桶模式(处理时间序列数据):
// 传感器数据桶
{
_id: "SENSOR001_202305",
sensorId: "SENSOR001",
month: "202305",
readings: [
{ timestamp: ISODate("2023-05-01T00:00:00Z"), value: 23.5 },
{ timestamp: ISODate("2023-05-01T00:05:00Z"), value: 23.7 },
// ...更多读数
],
stats: {
avgValue: 24.1,
maxValue: 28.5,
minValue: 22.3
}
}
- 计算模式(预聚合数据):
// 每日销售汇总
{
_id: "SALES_20230515",
date: ISODate("2023-05-15"),
totalSales: 125000,
categorySales: {
electronics: 80000,
clothing: 30000,
groceries: 15000
},
paymentMethods: {
credit: 70000,
debit: 40000,
cash: 15000
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn