文章目录
简介
MongoDB 是由 C++ 编写的分布式文件存储的开源数据库系统,其数据结构由键值对组成,以其灵活性、可扩展性和高性能而闻名,特别适合处理大量非结构化或半结构化数据。
核心特性:
- 文档数据模型
MongoDB 使用 BSON (Binary JSON) 格式存储数据,数据以文档形式组织在集合中:
{
"_id": ObjectId("5f9d7b3b9c9d6e1d7c8b9a9a"),
"name": "张三",
"age": 28,
"address": {
"city": "北京",
"street": "中关村大街"
},
"hobbies": ["阅读", "游泳", "编程"]
}
- 灵活的模式设计
无固定模式:同一集合中的文档可以有不同的字段结构
动态模式:字段可以随时添加或修改
嵌套文档:支持多级嵌套数据结构 - 查询能力
丰富的查询语言支持
索引支持(单字段、复合、多键、文本、地理空间等)
聚合框架提供复杂数据处理能力 - 扩展性
水平扩展:通过分片(Sharding)实现
垂直扩展:通过更强大的服务器实现
自动分片和负载均衡 - 高可用性
复制集(Replica Set)提供自动故障转移
数据冗余保障安全性
读写分离提高性能
适用场景:
- 需要快速迭代开发:灵活的模式适应需求变化
- 处理大量非结构化数据:如日志、社交媒体数据
- 需要水平扩展:大数据量、高吞吐量应用
- 地理位置查询:内置地理空间索引和查询
- 缓存层:高性能读写能力适合缓存场景
不适合的场景:
- 复杂事务:虽然支持多文档事务,但性能不如关系型数据库
- 严格的数据一致性要求:MongoDB 默认是最终一致性
- 复杂表连接:MongoDB 不擅长处理多表关联查询
- 高度结构化的固定模式数据:传统关系型数据库可能更合适
版本区别
- 4.0:多文档事务
- 4.2:分布式事务
- 4.4:可重试读写、增强聚合
- 5.0:时序集合、窗口函数
- 6.0:查询加密、时区支持增强
- 7.0:集群同步、查询优化
- 8.0:安全增强、分片优化、性能跃进
安装
MongoDB
选择版本和系统下载,安装过程中会安装 Mongodb Compass
,这是 MongoDB 的可视化管理工具
MongoDB Shell
- 取消勾选 Install just for you
- 添加到环境变量 Path:
C:\Program Files\mongosh
MongoDB Database Tools
添加到环境变量 Path:C:\Program Files\MongoDB\Tools\100\bin
Python库
pip install pymongo
配置数据库和日志文件
- 环境变量 Path 添加:
C:\Program Files\MongoDB\Server\7.0\bin
- 安装路径
C:\Program Files\MongoDB\Server\7.0\data
下新建文件夹db
和logs
- 指定数据库目录:
mongod --dbpath "C:\Program Files\MongoDB\Server\7.0\data\db"
- 访问 http://localhost:27017/
- 计算机 → 右键 → 管理 → 服务和应用程序 → 服务,可以看到服务正在运行,不常用的话设置成手动开启
基本连接
连接本地 MongoDB
mongosh "mongodb://localhost:27017"
连接带认证的数据库
mongosh "mongodb://username:password@localhost:27017/dbname?authSource=admin"
数据库操作
显示所有数据库
show dbs
切换/创建数据库
use users
显示当前数据库集合
show collections
集合操作
插入单个文档
db.users.insertOne({name:"张三", age: 28, skills: ["Python", "Java"]})
插入多个文档
db.users.insertMany([{name:"李四", age: 25}, {name:"王五", age: 30}])
查询文档
db.users.find() // 查询所有
db.users.find({age: {$gt: 25}}) // 条件查询
db.users.find({}, {name: 1, age: 1}) // 限制返回字段
db.users.find().sort({age: -1}) // 排序
db.users.find().skip(10).limit(5) // 分页
更新文档
db.users.updateOne({name: "张三"}, {$set: {age: 29}}) // 更新单个
db.users.updateMany({age: {$lt: 30}}, {$inc: {age: 1}}) // 更新多个
db.users.update({name: “张三”}, {$set: {“author.name”: “joe schmoe”}}) // 修改内嵌文档
删除文档
db.users.deleteOne({name: "张三"}) // 删除单个
db.users.deleteMany({age: {$lt: 25}}) // 删除多个
更新或插入文档
db.users.updateOne({name: "赵六"}, {$set: {age: 29}}, {upsert: true}) // 更新或插入
索引操作
创建索引
db.users.createIndex({name: 1}) // 单字段索引
db.users.createIndex({name: 1, age: -1}) // 复合索引
db.users.createIndex({email: 1}, {unique: true}) // 唯一索引
查看索引
db.users.getIndexes()
删除索引
db.users.dropIndex("name_1")
用户管理
创建管理员
use admin
db.createUser({
user: "admin",
pwd: "123456",
roles: ["root"]
})
创建用户
use mydb
db.createUser({
user: "mydbuser",
pwd: "123456",
roles: ["readWrite"]
})
查看用户
db.getUsers()
备份与恢复
mongodump --uri="mongodb://localhost:27017/mydb" --collection=users --out=C:\backup
mongorestore --uri="mongodb://localhost:27017/mydb" C:\backup\mydb\users.bson
mongoexport --uri="mongodb://localhost:27017/mydb" --collection=users --out=C:\backup\users.json
查看帮助
help
db.help()
db.users.help()
性能监控
查看数据库状态
db.stats()
查看集合状态
db.users.stats()
解释执行计划
db.users.find({age: {$gt: 25}}).explain("executionStats")
实用技巧
执行 JavaScript 文件
mongosh --file script.js
批处理模式
mongosh --eval "db.version()"
GUI
- 注册信息不用填,点 Finish
- 连接数据库:
create
→save
→connect
- 查询刚刚插入的信息
PyMongo
基本连接
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/') # 连接到本地 MongoDB 默认端口
# client = MongoClient('mongodb://username:password@localhost:27017/', authSource='admin') # 认证数据库
# client = MongoClient('mongodb://host1:27017,host2:27017,host3:27017/', replicaSet='myReplicaSet') # 连接副本集或分片集群
print(client.list_database_names()) # 获取数据库列表
client.close()
增删改查
import datetime
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/') # 连接本地MongoDB
db = client['test'] # 切换/创建数据库
collection = db['books'] # 获取集合
# 增
document = {
"title": "PyMongo教程",
"content": "MongoDB是NoSQL数据库",
"tags": ["mongodb", "python", "pymongo"],
"date": datetime.datetime.utcnow()
}
result = collection.insert_one(document) # 插入单个文档
print(f"插入文档ID: {result.inserted_id}")
documents = [
{"title": "Python基础", "views": 100, "date": datetime.datetime.utcnow()},
{"title": "MongoDB进阶", "views": 50, "date": datetime.datetime.utcnow()}
]
result = collection.insert_many(documents) # 插入多个文档
print(f"插入文档IDs: {result.inserted_ids}")
# 查
document = collection.find_one({"title": "PyMongo教程"}) # 查询单个文档
print(f"查询单个文档: {document}")
for document in collection.find({"views": {"$gt": 50}}): # 查询多个文档
print(f"查询多个文档: {document}")
for document in collection.find({}, {"title": 1, "date": 1}): # 带投影的查询(只返回指定字段)
print(f"带投影的查询: {document}")
cursor = collection.find({
"views": {"$gt": 10, "$lt": 100},
"date": {"$gte": datetime.datetime(2023, 1, 1)}
}).sort("views", -1).limit(5) # 高级查询
for document in cursor:
print(f"高级查询: {document}")
# 改
result = collection.update_one(
{"title": "PyMongo教程"},
{"$set": {"content": "更新后的内容"}}
) # 更新单个文档
print(f"匹配到{result.matched_count}个文档,修改了{result.modified_count}个文档")
result = collection.update_many(
{"views": {"$lt": 100}},
{"$inc": {"views": 10}}
) # 更新多个文档
print(f"匹配到{result.matched_count}个文档,修改了{result.modified_count}个文档")
result = collection.replace_one(
{"title": "PyMongo教程"},
{"new_title": "新标题", "new_content": "新内容"}
) # 替换文档
print(f"匹配到{result.matched_count}个文档,替换了{result.modified_count}个文档")
# 删
result = collection.delete_one({"new_title": "新标题"}) # 删除单个文档
print(f"删除了{result.deleted_count}个文档")
result = collection.delete_many({"views": {"$lt": 200}}) # 删除多个文档
print(f"删除了{result.deleted_count}个文档")
client.close()
批量操作
from pymongo import InsertOne, UpdateOne, DeleteOne
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/') # 连接本地MongoDB
db = client['test'] # 切换/创建数据库
collection = db['books'] # 获取集合
requests = [
InsertOne({"name": "Alice", "age": 25}),
UpdateOne({"name": "Bob"}, {"$set": {"age": 30}}),
DeleteOne({"name": "Charlie"})
]
result = collection.bulk_write(requests)
print(f"插入: {result.inserted_count}, 更新: {result.modified_count}, 删除: {result.deleted_count}")
client.close()
更新或插入
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/')
db = client['test']
collection = db['books']
result = collection.update_one(
{"title": "PyMongo教程"},
{"$set": {"content": "更新后的内容"}},
upsert=True
)
print(result)
client.close()
$操作符
查询操作符
比较操作符
操作符 | 描述 | 示例 |
---|---|---|
$eq | 等于 | { age: { $eq: 25 } } |
$ne | 不等于 | { status: { $ne: “inactive” } } |
$gt | 大于 | { score: { $gt: 90 } } |
$gte | 大于等于 | { votes: { $gte: 100 } } |
$lt | 小于 | { age: { $lt: 18 } } |
$lte | 小于等于 | { price: { $lte: 99.99 } } |
$in | 匹配数组中任意值 | { status: { $in: [“A”, “B”] } } |
$nin | 不匹配数组中的值 | { role: { $nin: [“admin”, “root”] } } |
逻辑操作符
操作符 | 描述 | 示例 |
---|---|---|
$and | 逻辑与 | { $and: [{ price: 10 }, { qty: { $lt: 100 } }] } |
$or | 逻辑或 | { $or: [{ qty: 100 }, { price: 1.99 }] } |
$not | 逻辑非 | { price: { $not: { $gt: 1.99 } } } |
$nor | 逻辑或非 | { $nor: [{ price: 1.99 }, { sale: true }] } |
元素操作符
操作符 | 描述 | 示例 |
---|---|---|
$exists | 字段存在性检查 | { qty: { $exists: true } } |
$type | 字段类型检查 | { price: { $type: “decimal” } } |
评估操作符
操作符 | 描述 | 示例 |
---|---|---|
$expr | 允许使用聚合表达式 | { $expr: { g t : [ " gt: [" gt:["spent", “$budget”] } } |
$jsonSchema | JSON模式验证 | { $jsonSchema: { required: [“name”] } } |
$mod | 取模运算 | { qty: { $mod: [4, 0] } } |
$regex | 正则匹配 | { name: { $regex: /^A/ } } |
$text | 文本搜索 | { $text: { $search: “coffee” } } |
$where | JavaScript表达式 | { $where: “this.credits == this.debits” } |
数组操作符
操作符 | 描述 | 示例 |
---|---|---|
$all | 匹配数组包含所有指定元素 | { tags: { $all: [“ssl”, “security”] } } |
$elemMatch | 匹配数组元素满足所有条件 | { results: { $elemMatch: { $gte: 80, $lt: 85 } } } |
$size | 匹配数组长度 | { tags: { $size: 3 } } |
地理空间操作符
操作符 | 描述 | 示例 |
---|---|---|
$geoWithin | 在几何图形内 | { loc: { $geoWithin: { $geometry: polygon } } } |
$geoIntersects | 与几何图形相交 | { loc: { $geoIntersects: { $geometry: line } } } |
$near | 附近点 | { loc: { $near: { $geometry: point } } } |
$nearSphere | 附近点(球面) | { loc: { $nearSphere: { $geometry: point } } } |
更新操作符
字段更新操作符
操作符 | 描述 | 示例 |
---|---|---|
$set | 设置字段值 | { $set: { status: “A” } } |
$setOnInsert | 只在插入时设置 | { $setOnInsert: { createdAt: new Date() } } |
$unset | 删除字段 | { $unset: { status: “” } } |
$rename | 重命名字段 | { $rename: { “nick”: “username” } } |
$inc | 数值增减 | { $inc: { quantity: -2 } } |
$mul | 数值乘法 | { $mul: { price: 1.25 } } |
$min | 取较小值 | { $min: { lowScore: 150 } } |
$max | 取较大值 | { $max: { highScore: 900 } } |
$currentDate | 设置当前日期 | { $currentDate: { lastModified: true } } |
数组更新操作符
操作符 | 描述 | 示例 |
---|---|---|
$ | 匹配数组元素 | { $set: { “grades.$.std”: 6 } } |
$[] | 匹配所有数组元素 | { $inc: { “grades.$[].score”: 10 } } |
$[] | 过滤数组元素 | { $set: { “grades.$[elem].score”: 100 } } |
$addToSet | 添加不重复元素 | { $addToSet: { tags: “database” } } |
$pop | 移除首/尾元素 | { $pop: { scores: 1 } } |
$pull | 移除匹配元素 | { $pull: { fruits: “apples” } } |
$push | 添加元素 | { $push: { scores: 89 } } |
$pullAll | 移除多个元素 | { $pullAll: { scores: [0, 5] } } |
位操作符
操作符 | 描述 | 示例 |
---|---|---|
$bit | 位操作 | { $bit: { flags: { and: 5 } } } |
聚合管道操作符
阶段操作符
操作符 | 描述 |
---|---|
$match | 过滤文档 |
$group | 分组计算 |
$sort | 排序 |
$project | 字段投影 |
$limit | 限制数量 |
$skip | 跳过文档 |
$unwind | 展开数组 |
$lookup | 多表关联 |
$facet | 多管道聚合 |
$bucket | 分桶计算 |
$count | 计数 |
表达式操作符
操作符 | 描述 | 示例 |
---|---|---|
$abs | 绝对值 | { $abs: “$value” } |
$add | 加法 | { $add: [“$price”, “$fee”] } |
$concat | 字符串连接 | { $concat: [“$firstName”, " ", “$lastName”] } |
$dateToString | 日期格式化 | { $dateToString: { format: “%Y-%m-%d”, date: “$date” } } |
$divide | 除法 | { $divide: [“$total”, “$count”] } |
$ifNull | 空值处理 | { $ifNull: [“$description”, “N/A”] } |
$multiply | 乘法 | { $multiply: [“$price”, “$quantity”] } |
$round | 四舍五入 | { $round: [“$value”, 2] } |
$sqrt | 平方根 | { $sqrt: “$value” } |
$strLenBytes | 字符串字节长度 | { $strLenBytes: “$name” } |
$substr | 子字符串 | { $substr: [“$name”, 0, 3] } |
$sum | 求和 | { $sum: “$scores” } |
$toLower | 转小写 | { $toLower: “$name” } |
$toUpper | 转大写 | { $toUpper: “$name” } |
$trunc | 截断小数 | { $trunc: [“$value”, 1] } |
特殊用途操作符
操作符 | 描述 | 示例 |
---|---|---|
$natural | 自然排序 | find().sort({ $natural: -1 }) |
$isolated | 隔离写操作 | update({ $isolated: 1 }, …) |
$comment | 添加查询注释 | find({ $comment: “查找VIP用户” }) |
TODO:聚合管道
变更流
变更流(Change Streams):实时监听数据库中的变更事件,可以捕获集合、数据库或整个集群的变更。该功能仅支持在副本集(Replica Set)环境下运行。
应用场景:
- 实时数据同步(主从数据库)
- 事件驱动架构
- 数据变更审计
- 实时分析处理
GridFS
GridFS:存储和检索大文件(超过16MB BSON文档限制)的规范,它将大文件分割成多个小文档(chunks)存储。
- 大文件支持:可存储超过16MB的文件
- 分块存储:自动将文件分割为255KB的块
- 元数据存储:可存储文件相关元信息
- 流式处理:支持流式上传和下载
应用场景
- 存储用户上传的图片/视频
- 管理大型文档(PDF/Word等)
- 备份文件系统
- 需要存储文件及其元数据的场景
常见问题
- 建索引后插入新数据是否需要重建索引?
不需要,MongoDB会自动更新索引。