MongoDB 详细教程
MongoDB 是一个开源的 NoSQL 文档数据库,提供高性能、高可用性和易扩展性。以下是 MongoDB 的全面教程:
1. MongoDB 简介
主要特点
- 文档存储:BSON 格式(类似 JSON)
- 无固定模式:集合中的文档可以有不同的结构
- 高性能:支持索引、聚合、内存映射
- 高可用:复制集(Replica Set)自动故障转移
- 水平扩展:分片(Sharding)支持
- 丰富查询语言:支持复杂查询和聚合操作
核心概念
- 数据库(Database):数据容器
- 集合(Collection):相当于关系型数据库的表
- 文档(Document):相当于表中的行,BSON 格式
- 字段(Field):文档中的键值对
2. MongoDB 安装
Linux 安装
# Ubuntu/Debian
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org
# 启动服务
sudo systemctl start mongod
sudo systemctl enable mongod
Mac 安装
brew tap mongodb/brew
brew install mongodb-community
brew services start mongodb-community
Windows 安装
- 从官网下载 MSI 安装包
- 运行安装向导
- 默认安装路径:
C:\Program Files\MongoDB\Server\<version>\bin
Docker 运行
docker run --name some-mongo -d mongo
3. MongoDB Shell 基本操作
连接 MongoDB
mongo # 连接本地默认实例
mongo --host <host> --port <port> # 连接远程实例
mongo "mongodb://user:pwd@host:port/db" # 带认证连接
常用命令
show dbs // 显示所有数据库
use dbname // 切换/创建数据库
show collections // 显示当前数据库的集合
db.collection.stats() // 查看集合统计信息
db.help() // 数据库帮助
db.collection.help() // 集合帮助
exit // 退出 shell
4. CRUD 操作
1. 插入文档
// 插入单个文档
db.users.insertOne({
name: "张三",
age: 25,
email: "zhangsan@example.com",
hobbies: ["读书", "游泳"],
address: { city: "北京", street: "朝阳路" }
})
// 插入多个文档
db.users.insertMany([
{ name: "李四", age: 30 },
{ name: "王五", age: 28 }
])
2. 查询文档
// 查询所有文档
db.users.find()
// 条件查询
db.users.find({ age: { $gt: 25 } }) // 年龄大于25
db.users.find({ name: /张/ }) // 名字包含"张"
// 投影(只返回指定字段)
db.users.find({}, { name: 1, age: 1 })
// 排序
db.users.find().sort({ age: 1 }) // 1升序,-1降序
// 分页
db.users.find().skip(10).limit(5) // 跳过10条,取5条
// 计数
db.users.countDocuments({ age: { $gt: 25 } })
3. 更新文档
// 更新单个文档
db.users.updateOne(
{ name: "张三" },
{ $set: { age: 26 } }
)
// 更新多个文档
db.users.updateMany(
{ age: { $lt: 30 } },
{ $inc: { age: 1 } } // 年龄加1
)
// 替换文档
db.users.replaceOne(
{ name: "张三" },
{ name: "张三", age: 27, email: "new@example.com" }
)
4. 删除文档
// 删除单个文档
db.users.deleteOne({ name: "张三" })
// 删除多个文档
db.users.deleteMany({ age: { $gt: 30 } })
// 删除集合
db.users.drop()
5. 索引
创建索引
// 单字段索引
db.users.createIndex({ name: 1 }) // 1升序,-1降序
// 复合索引
db.users.createIndex({ name: 1, age: -1 })
// 唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
// 文本索引(支持全文搜索)
db.articles.createIndex({ content: "text" })
索引管理
// 查看索引
db.users.getIndexes()
// 删除索引
db.users.dropIndex("name_1")
// 索引重建
db.users.reIndex()
6. 聚合框架
基本聚合
// 按年龄分组统计
db.users.aggregate([
{ $group: { _id: "$age", count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 5 }
])
常用聚合阶段
$match
:过滤文档$group
:分组$sort
:排序$project
:投影$limit
:限制数量$skip
:跳过文档$unwind
:展开数组$lookup
:关联查询
关联查询($lookup)
// orders 集合关联 users 集合
db.orders.aggregate([
{
$lookup: {
from: "users",
localField: "user_id",
foreignField: "_id",
as: "user_info"
}
}
])
7. 数据模型设计
1. 嵌入式文档
// 用户和地址嵌入
{
_id: ObjectId("..."),
name: "张三",
addresses: [
{ type: "home", city: "北京" },
{ type: "work", city: "上海" }
]
}
2. 引用式文档
// 用户集合
{
_id: ObjectId("user123"),
name: "张三"
}
// 订单集合
{
_id: ObjectId("order456"),
user_id: ObjectId("user123"),
amount: 100
}
设计原则
- 优先考虑嵌入:一对少、不频繁变化的数据
- 适当引用:一对多、频繁变化的数据
- 考虑读写比例:高频读取适合嵌入,高频更新适合引用
- 避免大文档:单个文档不超过16MB
8. 复制集(Replica Set)
配置复制集
- 创建配置文件(mongod.conf):
replication:
replSetName: "rs0"
- 启动多个 mongod 实例
mongod --port 27017 --dbpath /data/db1 --replSet rs0
mongod --port 27018 --dbpath /data/db2 --replSet rs0
mongod --port 27019 --dbpath /data/db3 --replSet rs0
- 初始化复制集
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27018" },
{ _id: 2, host: "localhost:27019" }
]
})
复制集命令
rs.status() // 查看状态
rs.add("host:port") // 添加成员
rs.remove("host:port") // 移除成员
rs.slaveOk() // 允许从节点读取
9. 分片(Sharding)
分片集群组件
- mongos:路由进程
- config servers:配置服务器
- shards:数据分片
配置分片集群
- 启动配置服务器
mongod --configsvr --replSet configReplSet --dbpath /data/configdb --port 27019
- 启动分片服务器
mongod --shardsvr --replSet shardReplSet --dbpath /data/shard1 --port 27018
- 启动 mongos
mongos --configdb configReplSet/localhost:27019 --port 27017
- 添加分片
sh.addShard("shardReplSet/localhost:27018")
- 启用分片
sh.enableSharding("mydb")
sh.shardCollection("mydb.users", { "_id": "hashed" })
10. 安全与认证
1. 启用认证
- 创建管理员用户
use admin
db.createUser({
user: "admin",
pwd: "password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
- 启用认证(修改 mongod.conf)
security:
authorization: enabled
2. 用户角色
- read:只读
- readWrite:读写
- dbAdmin:数据库管理
- userAdmin:用户管理
- clusterAdmin:集群管理
- root:超级用户
3. 连接认证
mongo -u username -p password --authenticationDatabase admin
11. 备份与恢复
1. mongodump/mongorestore
# 备份整个数据库
mongodump --host localhost --port 27017 --out /backup/
# 备份指定集合
mongodump --db mydb --collection users --out /backup/
# 恢复数据库
mongorestore --host localhost --port 27017 /backup/
2. mongoexport/mongoimport
# 导出为JSON
mongoexport --db mydb --collection users --out users.json
# 导出为CSV
mongoexport --db mydb --collection users --type=csv --fields name,age --out users.csv
# 导入数据
mongoimport --db mydb --collection users --file users.json
12. 性能优化
- 合理使用索引:为常用查询创建索引
- 查询优化:使用投影只返回必要字段
- 批量操作:使用 bulkWrite 减少网络开销
- 适当分片:大数据集考虑分片
监控工具:
- mongostat
- mongotop
- db.serverStatus()
- explain() 分析查询
13. 驱动程序示例
Node.js
const { MongoClient } = require('mongodb');
async function main() {
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
try {
await client.connect();
const database = client.db("mydb");
const collection = database.collection("users");
// 插入文档
await collection.insertOne({ name: "Alice", age: 30 });
// 查询文档
const users = await collection.find({ age: { $gt: 25 } }).toArray();
console.log(users);
} finally {
await client.close();
}
}
main().catch(console.error);
Python
from pymongo import MongoClient
client = MongoClient('localhost', 27017)
db = client['mydb']
collection = db['users']
# 插入文档
collection.insert_one({'name': 'Bob', 'age': 35})
# 查询文档
for user in collection.find({'age': {'$gt': 25}}):
print(user)
Java
import com.mongodb.client.*;
import org.bson.Document;
public class MongoDBExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("mydb");
MongoCollection<Document> collection = database.getCollection("users");
// 插入文档
Document doc = new Document("name", "Charlie")
.append("age", 40);
collection.insertOne(doc);
// 查询文档
for (Document user : collection.find(Filters.gt("age", 25))) {
System.out.println(user.toJson());
}
mongoClient.close();
}
}
14. 常见应用场景实现
1. 日志存储
// 日志文档结构
{
timestamp: new Date(),
level: "INFO",
message: "User logged in",
metadata: { userId: "123", ip: "192.168.1.1" }
}
// 按时间分片
sh.shardCollection("logs.messages", { "timestamp": 1 })
2. 商品目录
// 商品文档结构
{
_id: ObjectId("..."),
name: "智能手机",
price: 2999,
categories: ["电子产品", "手机"],
attributes: {
brand: "Apple",
model: "iPhone 13",
color: "黑色"
},
stock: 100,
reviews: [
{ userId: "user1", rating: 5, comment: "很好用" },
{ userId: "user2", rating: 4, comment: "还不错" }
]
}
// 多条件查询
db.products.find({
price: { $lt: 3000 },
"attributes.brand": "Apple",
categories: "手机"
})
3. 地理位置查询
// 创建地理位置索引
db.places.createIndex({ location: "2dsphere" })
// 插入位置数据
db.places.insertOne({
name: "中央公园",
location: { type: "Point", coordinates: [ -73.97, 40.77 ] }
})
// 附近地点查询
db.places.find({
location: {
$near: {
$geometry: { type: "Point", coordinates: [ -73.98, 40.78 ] },
$maxDistance: 1000 // 1公里内
}
}
})
MongoDB 是一个功能强大且灵活的 NoSQL 数据库,适用于各种现代应用开发场景。通过本教程,您应该能够掌握 MongoDB 的核心概念和基本操作,并能够开始在实际项目中使用它。