MongoDB 速查表
通过实战实验和真实场景学习 MongoDB NoSQL 数据库管理。LabEx 提供全面的 MongoDB 课程,涵盖基本操作、文档查询、聚合管道、索引策略和高级技术。掌握 MongoDB 的面向文档数据模型,以构建可扩展且灵活的数据库应用程序。
数据库和集合管理
显示数据库:show dbs
显示 MongoDB 服务器上的所有数据库。
// 显示所有数据库
show dbs
// 显示当前数据库
db
// 获取数据库统计信息
db.stats()
// 获取数据库帮助
db.help()
使用数据库:use database_name
切换到指定的数据库(如果不存在则创建)。
// 切换到 myapp 数据库
use myapp
// 通过插入数据创建数据库
use newdb
db.users.insertOne({name: "John"})
登录后即可答题并追踪学习进度
use newdb 会发生什么?删除数据库:db.dropDatabase()
删除当前数据库及其所有集合。
// 删除当前数据库
db.dropDatabase()
// 确认数据库名称
use myapp
db.dropDatabase()
显示集合:show collections
列出当前数据库中的所有集合。
// 显示所有集合
show collections
// 替代方法
db.runCommand("listCollections")
创建集合:db.createCollection()
创建具有可选配置的新集合。
// 创建简单集合
db.createCollection('users')
// 创建带选项的集合
db.createCollection('logs', {
capped: true,
size: 1000000,
max: 1000,
})
删除集合:db.collection.drop()
删除一个集合及其所有文档。
// 删除 users 集合
db.users.drop()
// 检查集合是否已删除
show collections
文档结构与信息
集合统计信息:db.collection.stats()
显示有关集合的全面统计信息,包括大小、文档计数和索引信息。
// 集合统计信息
db.users.stats()
// 计数文档
db.users.countDocuments()
// 估计计数(更快)
db.users.estimatedDocumentCount()
// 检查集合索引
db.users.getIndexes()
示例文档:db.collection.findOne()
检索示例文档以了解结构和数据类型。
// 获取一个文档
db.users.findOne()
// 获取特定文档
db.users.findOne({ name: 'John' })
// 获取显示所有字段的文档
db.users.findOne({}, { _id: 0 })
浏览数据:db.collection.find().limit()
通过分页和格式化浏览集合数据。
// 前 5 个文档
db.users.find().limit(5)
// 跳过和限制(分页)
db.users.find().skip(10).limit(5)
// 漂亮格式化输出
db.users.find().pretty()
文档插入 (创建)
插入一个:db.collection.insertOne()
向集合中添加单个文档。
// 插入单个文档
db.users.insertOne({
name: 'John Doe',
age: 30,
email: 'john@example.com',
})
// 插入自定义 _id
db.users.insertOne({
_id: 'custom_id_123',
name: 'Jane Doe',
status: 'active',
})
登录后即可答题并追踪学习进度
db.users.insertOne() 返回什么?插入多个:db.collection.insertMany()
在单个操作中添加多个文档。
// 插入多个文档
db.users.insertMany([
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 35 },
{ name: 'Charlie', age: 28 },
])
// 插入带选项的多个文档
db.users.insertMany(
[
{ name: 'Dave', age: 40 },
{ name: 'Eve', age: 22 },
],
{ ordered: false },
)
插入带日期:new Date()
添加带有时间戳字段的文档。
// 插入当前日期
db.posts.insertOne({
title: '我的博客文章',
content: '此处是文章内容',
createdAt: new Date(),
publishDate: ISODate('2024-01-15'),
})
插入嵌套文档
添加包含嵌入式对象和数组的文档。
// 插入嵌套对象
db.users.insertOne({
name: 'John Doe',
address: {
street: '123 Main St',
city: 'New York',
zip: '10001',
},
hobbies: ['reading', 'swimming', 'coding'],
})
文档查询 (读取)
基本查找:db.collection.find()
根据查询条件检索文档。
// 查找所有文档
db.users.find()
// 带条件的查找
db.users.find({ age: 30 })
// 带多个条件的查找 (AND)
db.users.find({ age: 30, status: 'active' })
// 带 OR 条件的查找
db.users.find({ $or: [{ age: 25 }, { age: 30 }] })
投影:db.collection.find({}, {})
控制结果中返回哪些字段。
// 包含特定字段
db.users.find({}, { name: 1, age: 1 })
// 排除特定字段
db.users.find({}, { password: 0, _id: 0 })
// 嵌套字段投影
db.users.find({}, { 'address.city': 1 })
查询操作符:$gt, $lt, $in, 等
使用比较和逻辑操作符进行复杂查询。
// 大于,小于
db.users.find({ age: { $gt: 25, $lt: 40 } })
// 在数组中
db.users.find({ status: { $in: ['active', 'pending'] } })
// 不等于
db.users.find({ status: { $ne: 'inactive' } })
// 存在
db.users.find({ email: { $exists: true } })
登录后即可答题并追踪学习进度
$gt 是什么意思?文本搜索:$text, $regex
使用文本和模式匹配搜索文档。
// 文本搜索 (需要文本索引)
db.posts.find({ $text: { $search: 'mongodb tutorial' } })
// 正则表达式搜索
db.users.find({ name: { $regex: '^John', $options: 'i' } })
// 不区分大小写的搜索
db.users.find({ email: { $regex: '@gmail.com$' } })
文档更新
更新一个:db.collection.updateOne()
修改第一个匹配查询条件的文档。
// 更新单个字段
db.users.updateOne({ name: 'John Doe' }, { $set: { age: 31 } })
// 更新多个字段
db.users.updateOne(
{ _id: ObjectId('...') },
{ $set: { age: 31, status: 'updated' } },
)
// Upsert (如果未找到则插入)
db.users.updateOne(
{ name: 'New User' },
{ $set: { age: 25 } },
{ upsert: true },
)
更新多个:db.collection.updateMany()
修改所有匹配查询条件的文档。
// 更新多个文档
db.users.updateMany({ status: 'inactive' }, { $set: { status: 'archived' } })
// 增加值
db.posts.updateMany({ category: 'tech' }, { $inc: { views: 1 } })
更新操作符:$set, $unset, $push
使用各种操作符修改文档字段。
// 设置和取消设置字段
db.users.updateOne(
{ name: 'John' },
{ $set: { lastLogin: new Date() }, $unset: { temp: '' } },
)
// 推送到数组
db.users.updateOne({ name: 'John' }, { $push: { hobbies: 'gaming' } })
登录后即可答题并追踪学习进度
$set 执行什么操作?// 从数组中拉取 (移除)
db.users.updateOne({ name: 'John' }, { $pull: { hobbies: 'reading' } })
替换文档:db.collection.replaceOne()
替换整个文档,但 _id 字段除外。
// 替换整个文档
db.users.replaceOne(
{ name: 'John Doe' },
{
name: 'John Smith',
age: 35,
email: 'johnsmith@example.com',
},
)
数据聚合
基本聚合:db.collection.aggregate()
通过聚合管道阶段处理数据。
// 分组并计数
db.users.aggregate([{ $group: { _id: '$status', count: { $sum: 1 } } }])
// 匹配并分组
db.orders.aggregate([
{ $match: { status: 'completed' } },
{ $group: { _id: '$customerId', total: { $sum: '$amount' } } },
])
常用阶段:$match, $group, $sort
使用管道阶段来转换和分析数据。
// 复杂聚合管道
db.sales.aggregate([
{ $match: { date: { $gte: ISODate('2024-01-01') } } },
{
$group: {
_id: '$product',
totalSales: { $sum: '$amount' },
avgPrice: { $avg: '$price' },
},
},
{ $sort: { totalSales: -1 } },
{ $limit: 10 },
])
聚合操作符:$sum, $avg, $max
计算统计值并执行数学运算。
// 统计运算
db.products.aggregate([
{
$group: {
_id: '$category',
maxPrice: { $max: '$price' },
minPrice: { $min: '$price' },
avgPrice: { $avg: '$price' },
count: { $sum: 1 },
},
},
])
投影阶段:$project
转换文档结构并创建计算字段。
// 投影并计算字段
db.users.aggregate([
{
$project: {
name: 1,
age: 1,
isAdult: { $gte: ['$age', 18] },
fullName: { $concat: ['$firstName', ' ', '$lastName'] },
},
},
])
文档删除
删除一个:db.collection.deleteOne()
删除第一个匹配查询条件的文档。
// 删除单个文档
db.users.deleteOne({ name: 'John Doe' })
// 按 ID 删除
db.users.deleteOne({ _id: ObjectId('...') })
// 带条件的删除
db.posts.deleteOne({ status: 'draft', author: 'unknown' })
删除多个:db.collection.deleteMany()
删除所有匹配查询条件的文档。
// 删除多个文档
db.users.deleteMany({ status: 'inactive' })
// 删除所有文档 (请小心!)
db.temp_collection.deleteMany({})
// 带日期条件的删除
db.logs.deleteMany({
createdAt: { $lt: new Date('2024-01-01') },
})
查找并删除:db.collection.findOneAndDelete()
在一个原子操作中查找并删除文档。
// 查找并删除
const deletedDoc = db.users.findOneAndDelete({ status: 'pending' })
// 查找并删除带选项
db.queue.findOneAndDelete({ processed: false }, { sort: { priority: -1 } })
索引与性能
创建索引:db.collection.createIndex()
在字段上创建索引以加速查询。
// 单字段索引
db.users.createIndex({ email: 1 })
// 复合索引
db.users.createIndex({ status: 1, createdAt: -1 })
// 用于搜索的文本索引
db.posts.createIndex({ title: 'text', content: 'text' })
// 唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
索引管理:getIndexes(), dropIndex()
查看和管理集合上现有的索引。
// 列出所有索引
db.users.getIndexes()
// 删除特定索引
db.users.dropIndex({ email: 1 })
// 按名称删除索引
db.users.dropIndex('email_1')
// 删除所有索引,_id 除外
db.users.dropIndexes()
查询性能:explain()
分析查询执行和性能统计信息。
// 解释查询执行
db.users.find({ age: { $gt: 25 } }).explain('executionStats')
// 检查索引是否被使用
db.users.find({ email: 'john@example.com' }).explain()
// 分析聚合性能
db.users
.aggregate([
{ $match: { status: 'active' } },
{ $group: { _id: '$department', count: { $sum: 1 } } },
])
.explain('executionStats')
性能提示
优化 MongoDB 查询和操作的最佳实践。
// 使用投影限制数据传输
db.users.find({ status: 'active' }, { name: 1, email: 1 })
// 限制结果以获得更好的性能
db.posts.find().sort({ createdAt: -1 }).limit(10)
// 使用 hint 强制使用特定索引
db.users.find({ age: 25 }).hint({ age: 1 })
MongoDB Shell 与连接
连接到 MongoDB: mongosh
启动 MongoDB shell 并连接到不同的实例。
# 连接到本地 MongoDB
mongosh
# 连接到特定主机和端口
mongosh "mongodb://localhost:27017"
# 连接到远程服务器
mongosh "mongodb://username:password@host:port/database"
# 带选项连接
mongosh --host localhost --port 27017
Shell 帮助程序:help, exit
获取帮助信息并管理 shell 会话。
// 一般帮助
help
// 数据库特定帮助
db.help()
// 集合特定帮助
db.users.help()
// 退出 shell
exit
Shell 变量和设置
配置 shell 行为并使用 JavaScript 变量。
// 设置变量
var myQuery = { status: 'active' }
db.users.find(myQuery)
// 配置显示选项
db.users.find().pretty()
// 显示执行时间
db.users.find({ age: 25 }).explain('executionStats')
// 在 shell 中使用 JavaScript
var user = db.users.findOne({ name: 'John' })
print('用户年龄:' + user.age)
数据导入与导出
导入数据:mongoimport
将 JSON、CSV 或 TSV 文件中的数据加载到 MongoDB。
# 导入 JSON 文件
mongoimport --db myapp --collection users --file users.json
# 导入 CSV 文件
mongoimport --db myapp --collection products \
--type csv --headerline --file products.csv
# 带 upsert 导入
mongoimport --db myapp --collection users \
--file users.json --mode upsert
导出数据:mongoexport
将 MongoDB 数据导出为 JSON 或 CSV 格式。
# 导出为 JSON
mongoexport --db myapp --collection users \
--out users.json
# 导出为 CSV
mongoexport --db myapp --collection users \
--type csv --fields name,email,age --out users.csv
# 带查询导出
mongoexport --db myapp --collection users \
--query '{"status":"active"}' --out active_users.json
备份:mongodump
创建 MongoDB 数据库的二进制备份。
# 备份整个数据库
mongodump --db myapp --out /backup/
# 备份特定集合
mongodump --db myapp --collection users --out /backup/
# 带压缩备份
mongodump --db myapp --gzip --out /backup/
恢复:mongorestore
从二进制备份中恢复 MongoDB 数据。
# 恢复数据库
mongorestore --db myapp /backup/myapp/
# 带 drop 恢复
mongorestore --db myapp --drop /backup/myapp/
# 恢复压缩备份
mongorestore --gzip --db myapp /backup/myapp/
MongoDB 安装与设置
MongoDB 社区服务器
下载并安装 MongoDB 社区版。
# Ubuntu/Debian
sudo apt-get install -y mongodb-org
# 启动 MongoDB 服务
sudo systemctl start mongod
# 启用自动启动
sudo systemctl enable mongod
# 检查状态
sudo systemctl status mongod
Docker 安装
使用 Docker 容器运行 MongoDB。
# 拉取 MongoDB 镜像
docker pull mongo
# 运行 MongoDB 容器
docker run --name mongodb -d \
-p 27017:27017 \
-v mongodb_data:/data/db \
mongo
# 连接到容器
docker exec -it mongodb mongosh
MongoDB Compass (GUI)
安装并使用 MongoDB 的官方图形界面工具。
# 从 mongodb.com 下载
# 使用连接字符串连接
mongodb://localhost:27017
# 可用功能:
# - 可视化查询构建器
# - 模式分析
# - 性能监控
# - 索引管理
配置与安全
身份验证:创建用户
使用适当的角色和权限设置数据库用户。
// 创建管理员用户
use admin
db.createUser({
user: "admin",
pwd: "securepassword",
roles: [{role: "root", db: "admin"}]
})
// 创建数据库用户
use myapp
db.createUser({
user: "appuser",
pwd: "password123",
roles: [{role: "readWrite", db: "myapp"}]
})
启用身份验证
配置 MongoDB 要求身份验证。
# 编辑 /etc/mongod.conf
security:
authorization: enabled
# 重启 MongoDB
sudo systemctl restart mongod
# 带身份验证连接
mongosh -u admin -p --authenticationDatabase admin
副本集:rs.initiate()
设置副本集以实现高可用性。
// 初始化副本集
rs.initiate({
_id: 'myReplicaSet',
members: [
{ _id: 0, host: 'mongodb1:27017' },
{ _id: 1, host: 'mongodb2:27017' },
{ _id: 2, host: 'mongodb3:27017' },
],
})
// 检查副本集状态
rs.status()
配置选项
常见的 MongoDB 配置设置。
# mongod.conf 示例
storage:
dbPath: /var/lib/mongodb
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
net:
port: 27017
bindIp: 127.0.0.1
processManagement:
fork: true
错误处理与调试
常见错误及解决方案
识别并修复经常遇到的 MongoDB 问题。
// 连接错误
// 检查 MongoDB 是否正在运行
sudo systemctl status mongod
// 检查端口是否可用
netstat -tuln | grep 27017
// 重复键错误处理
try {
db.users.insertOne({email: "existing@example.com"})
} catch (e) {
if (e.code === 11000) {
print("电子邮件已存在")
}
}
监控:db.currentOp(), db.serverStatus()
监控数据库操作和服务器性能。
// 检查当前操作
db.currentOp()
// 终止长时间运行的操作
db.killOp(operationId)
// 服务器状态
db.serverStatus()
// 连接统计信息
db.runCommand({ connPoolStats: 1 })
分析:db.setProfilingLevel()
启用分析以分析慢速操作。
// 为慢速操作 (>100ms) 启用分析
db.setProfilingLevel(1, { slowms: 100 })
// 为所有操作启用分析
db.setProfilingLevel(2)
// 查看分析器数据
db.system.profile.find().sort({ ts: -1 }).limit(5)
// 禁用分析
db.setProfilingLevel(0)
高级操作
事务:session.startTransaction()
使用多文档事务确保数据一致性。
// 启动会话和事务
const session = db.getMongo().startSession()
session.startTransaction()
try {
const users = session.getDatabase('myapp').users
const accounts = session.getDatabase('myapp').accounts
users.insertOne({ name: 'John', balance: 100 })
accounts.updateOne({ userId: 'john' }, { $inc: { balance: -100 } })
session.commitTransaction()
} catch (error) {
session.abortTransaction()
} finally {
session.endSession()
}
变更流:db.collection.watch()
实时监控集合中的变化。
// 监控集合变化
const changeStream = db.users.watch()
changeStream.on('change', (change) => {
console.log('检测到变化:', change)
})
// 带过滤条件监控
const pipeline = [{ $match: { operationType: 'insert' } }]
const changeStream = db.users.watch(pipeline)