MongoDB作为当下最流行的NoSQL数据库,其灵活的文档模型和强大的查询能力让它成为现代应用开发的首选。无论你是数据库新手还是有经验的开发者,本文将带你从零开始掌握MongoDB的核心技能,建立扎实的基础。
MongoDB简介与安装配置
MongoDB是什么?它是一个基于分布式文件存储的开源文档数据库,将数据存储为JSON格式的文档,支持动态查询、索引和水平扩展。
核心优势
灵活的数据模型 :无需预定义表结构,文档结构可以根据需求随时调整
强大的查询能力 :支持丰富的查询操作符和聚合管道
高可扩展性 :支持水平分区,能够处理海量数据
内存映射:自动管理内存使用,提供高性能数据访问
安装与配置
Windows环境下安装:
bash
# 使用winget安装MongoDB Community版
winget install MongoDB.Server
winget install MongoDB.Shell
Docker方式部署(推荐):
bash
docker run -d --name mongodb \
-p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password \
mongo:latest
验证安装:
javascript
// 连接到MongoDB
mongosh "mongodb://admin:password@localhost:27017"
// 查看版本信息
db.version()
// 查看服务器状态
db.serverStatus()
核心概念与数据模型
基本概念对比
| SQL概念 | MongoDB对应 | 说明 |
|---|---|---|
| 数据库 | database | 数据处理单元 |
| 表 | collection | 文档的容器 |
| 行 | document | JSON格式的数据记录 |
| 列 | field | 文档中的字段 |
| 主键 | _id | 自动生成的唯一标识 |
javascript
// 文档示例:用户数据
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "张三",
"age": 28,
"email": "zhangsan@example.com",
"address": {
"city": "北京",
"district": "海淀区"
},
"hobbies": ["阅读", "编程", "运动"],
"createdAt": ISODate("2025-12-19T10:30:00.000Z")
}
数据类型
MongoDB支持丰富的数据类型:
- String:字符串类型
- Integer:整数(32位和64位)
- Boolean:布尔值
- Double:浮点数
- Arrays:数组
- Object:嵌套对象
- Date:日期时间
- ObjectId:12字节唯一标识符
CRUD基础操作实战
创建数据库与集合
javascript
// 切换到目标数据库(不存在则自动创建)
use blogDB
// 创建集合(可选,插入数据时自动创建)
db.createCollection("users")
db.createCollection("articles")
// 查看当前数据库的集合
db.getCollectionNames()
数据插入操作
单文档插入:
javascript
// 插入单个用户文档
db.users.insertOne({
name: "李四",
age: 25,
email: "lisi@example.com",
createdAt: new Date()
})
// 返回结果包含插入文档的_id
// {"acknowledged":true,"insertedId":ObjectId("...")}
批量插入:
javascript
// 插入多个文档
db.users.insertMany([
{
name: "王五",
age: 30,
email: "wangwu@example.com",
city: "上海"
},
{
name: "赵六",
age: 22,
email: "zhaoliu@example.com",
city: "广州"
}
])
// 批量插入结果
// {"acknowledged":true,"insertedIds":[ObjectId("..."),ObjectId("...")]}
数据查询操作
基础查询:
javascript
// 查询所有文档
db.users.find()
// 带条件查询 - 查找年龄大于等于25的用户
db.users.find({ age: { $gte: 25 } })
// 精确查找
db.users.find({ name: "张三" })
// 查询单个文档
db.users.findOne({ email: "zhangsan@example.com" })
高级查询操作符:
javascript
// 比较操作符
db.users.find({ age: { $lt: 30, $gt: 20 } }) // 20 < age < 30
db.users.find({ age: { $in: [20, 25, 30] } }) // age等于数组中任意值
// 逻辑操作符
db.users.find({
$and: [
{ age: { $gte: 25 } },
{ city: "上海" }
]
})
db.users.find({
$or: [
{ age: { $lt: 25 } },
{ city: "北京" }
]
})
// 正则表达式查询
db.users.find({ name: /张/ }) // 名字包含"张"
db.users.find({ email: /@.+\.com$/ }) // 邮箱以.com结尾
查询结果处理:
javascript
// 限制返回数量
db.users.find().limit(10)
// 跳过指定数量
db.users.find().skip(20).limit(10)
// 排序
db.users.find().sort({ age: 1 }) // 1升序,-1降序
db.users.find().sort({ age: -1, name: 1 })
// 字段投影 - 指定返回字段
db.users.find({}, {
name: 1,
age: 1,
_id: 0 // 不返回_id字段
})
数据更新操作
更新单个文档:
javascript
// 更新指定用户的年龄
db.users.updateOne(
{ name: "张三" }, // 查询条件
{
$set: { age: 29 }, // 设置新值
$currentDate: { updatedAt: true } // 更新时间戳
}
)
批量更新文档:
javascript
// 更新所有北京的用户的年龄+1
db.users.updateMany(
{ city: "北京" },
{ $inc: { age: 1 } } // 自增操作符
)
更新操作符详解:
javascript
// $set - 设置字段值
db.users.updateOne(
{ name: "张三" },
{ $set: {
"address.city": "上海",
"status": "active"
}}
)
// $unset - 删除字段
db.users.updateOne(
{ name: "李四" },
{ $unset: { temporaryField: "" } }
)
// $push - 向数组添加元素
db.users.updateOne(
{ name: "张三" },
{ $push: { hobbies: "旅游" } }
)
// $pull - 从数组移除元素
db.users.updateOne(
{ name: "张三" },
{ $pull: { hobbies: "编程" } }
)
// $addToSet - 避免重复添加
db.users.updateOne(
{ name: "张三" },
{ $addToSet: { hobbies: "烘焙" } }
)
数据删除操作
删除文档:
javascript
// 删除单个文档
db.users.deleteOne({ name: "李四" })
// 批量删除文档
db.users.deleteMany({ age: { $lt: 20 } })
// 删除所有文档(保留集合结构)
db.users.deleteMany({})
删除集合和数据库:
javascript
// 删除集合
db.users.drop()
// 删除数据库
db.dropDatabase()
索引优化与查询性能
索引基础
为什么需要索引?想象一下在一本没有目录的书中寻找特定内容,索引就如同书的目录,能大幅加速数据查找。
javascript
// 查看集合的索引
db.users.getIndexes()
// 创建单字段索引
db.users.createIndex({ name: 1 }) // 1升序,-1降序
db.users.createIndex({ email: 1 }, { unique: true }) // 唯一索引
// 创建复合索引
db.users.createIndex({ city: 1, age: -1 })
// 创建TTL索引(自动过期)
db.users.createIndex(
{ createdAt: 1 },
{
expireAfterSeconds: 604800, // 7天后自动删除
name: "ttl_7days"
}
)
复合索引设计原则
javascript
// 等值查询 + 排序场景
// 查询:db.users.find({ city: "上海" }).sort({ age: -1 })
// 索引:{ city: 1, age: -1 }
db.users.createIndex({ city: 1, age: -1 })
// 多条件等值查询
// 查询:db.users.find({ city: "上海", status: "active" })
// 索引:{ city: 1, status: 1 }
db.users.createIndex({ city: 1, status: 1 })
// 包含数组字段的索引
db.users.createIndex({ hobbies: 1 }) // 多键索引
查询执行计划分析
javascript
// 查看查询执行计划
db.users.find({ age: { $gte: 25 } }).explain("executionStats")
// 强制使用特定索引
db.users.find({ name: "张三" }).hint({ name: 1 })
// 创建文本索引支持全文搜索
db.articles.createIndex(
{ title: "text", content: "text" },
{
weights: { title: 10, content: 5 }, // 标题权重更高
name: "text_search_idx"
}
)
// 文本搜索查询
db.articles.find(
{ $text: { $search: "MongoDB 教程" } },
{ score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })
索引管理最佳实践
javascript
// 索引使用情况统计
db.users.aggregate([
{ $indexStats: {} }
])
// 删除不需要的索引
db.users.dropIndex("index_name")
// 查看所有索引大小
db.users.aggregate([
{
$collStats: {
indexSizes: {}
}
}
])
实践项目:博客系统数据模型
让我们通过一个简单的博客系统来综合运用所学知识:
数据结构设计
javascript
// 1. 用户集合
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["username", "email"],
properties: {
username: { bsonType: "string", minLength: 3 },
email: {
bsonType: "string",
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
password: { bsonType: "string", minLength: 6 },
profile: { bsonType: "object" },
roles: { bsonType: "array" },
createdAt: { bsonType: "date" },
updatedAt: { bsonType: "date" }
}
}
}
})
// 2. 文章集合
db.createCollection("posts", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["title", "content", "authorId"],
properties: {
title: { bsonType: "string", minLength: 1 },
content: { bsonType: "string", minLength: 10 },
authorId: { bsonType: "objectId" },
tags: { bsonType: "array", items: { bsonType: "string" } },
status: {
enum: ["draft", "published", "archived"]
},
viewCount: { bsonType: "int", minimum: 0 },
createdAt: { bsonType: "date" },
publishedAt: { bsonType: "date" }
}
}
}
})
实战操作示例
javascript
// 创建用户
db.users.insertOne({
username: "blog_admin",
email: "admin@blog.com",
password: "hashed_password",
profile: {
displayName: "博客管理员",
bio: "负责博客系统维护",
avatar: "/uploads/avatar1.jpg"
},
roles: ["admin", "editor"],
createdAt: new Date(),
updatedAt: new Date()
})
// 创建文章
db.posts.insertOne({
title: "MongoDB基础教程",
content: "这是一份详细的MongoDB入门指南...",
authorId: ObjectId("507f1f77bcf86cd799439011"),
tags: ["MongoDB", "NoSQL", "数据库"],
status: "published",
viewCount: 0,
createdAt: new Date(),
publishedAt: new Date()
})
// 查询用户发布的文章
db.posts.find({
authorId: ObjectId("507f1f77bcf86cd799439011"),
status: "published"
}).sort({ publishedAt: -1 })
性能优化实践
javascript
// 创建优化索引
db.posts.createIndex({ authorId: 1, status: 1, publishedAt: -1 })
db.posts.createIndex({ tags: 1, publishedAt: -1 })
db.posts.createIndex({ viewCount: -1 })
db.users.createIndex({ email: 1 }, { unique: true })
// 使用投影优化查询性能
db.posts.find(
{ status: "published", tags: "MongoDB" },
{
title: 1,
tags: 1,
viewCount: 1,
publishedAt: 1,
_id: 0
}
).limit(10)
这份MongoDB基础教程为你建立了扎实的技术地基。从安装配置到CRUD操作,从索引优化到实战项目,每一个环节都是实际开发中必需的技能。掌握这些基础知识后,你已经具备了使用MongoDB进行应用开发的核心能力。接下来的进阶教程将深入探讨聚合框架、事务管理和性能调优等高级主题。