36.MongoDB总结

36.总结


36.1 核心要点速览

SQL 和 NoSQL

对比维度 SQL NoSQL
数据模型 - 表格(行×列)
- 固定模式(Schema)
- 文档(JSON/BSON)、键值、列族、图
- 动态模式,灵活
查询语言 - 标准化 SQL
- 支持复杂查询、聚合、联表
- 各自接口(如 MongoDB 查询、Redis GET)
- 依赖具体实现
事务支持 - 完整 ACID(原子性、一致性、隔离性、持久性) - 通常“最终一致”
- 部分产品支持限域事务
性能 - 优化后复杂联表与事务性能优
- 适合结构化查询
- 高并发、低延迟
- 大规模水平扩展
适用场景 - 金融、电商等高一致性需求
- 复杂关系建模
- 日志、社交、物联网等半/非结构化数据
- 高吞吐缓存
优势 - 生态成熟、工具丰富
- 数据完整性高
- 扩展性强、灵活性高
- 支持多样数据模型
局限 - 模式固定、扩展复杂
- 海量并发场景受限
- 标准化查询缺失
- 复杂事务与关联查询能力弱

NoSQL 类型对比

类型 代表工具 主要优点 主要缺点
键值存储 Redis、Memcached、DynamoDB - 超高性能
- 简单模型
- 易水平扩展
- 仅键值对
- 无复杂查询
- 一致性风险
列式存储 HBase、Cassandra、Bigtable - 列级压缩高效
- OLAP 分析优
- 写入与更新慢
- 全表/多列查询低效
文档存储 MongoDB、CouchDB、Couchbase - 结构灵活
- 水平扩展
- 强查询功能
- 事务与一致性弱
- 复杂建模难

MongoDB下载安装

步骤

  • 获取安装包

    • 官方下载页获取 Community Edition
    • 可选格式:msi(向导式安装)、zip(便携解压)、Docker 镜像
  • 安装流程

    • 对于 msi:一路“Next”完成
    • 对于 zip:解压后手动配置环境变量
    • 对于 Docker:拉取镜像并运行容器
  • 服务运行账户

    • Network Service user:Windows 内置低权限账户,安全风险最小
    • Local User / Domain User:自定义账户,可精细控制文件与网络访问
    • 仅影响操作系统层面权限,不改动数据库内部用户认证
  • 可选组件

    • MongoDB Compass:官方 GUI 可视化管理工具,命令行不熟悉者推荐
    • 可根据需求勾选,无需强制安装
  • 安装后验证

    • 打开“服务”窗口,确认 “MongoDB” 服务存在且设为“自动”启动

安装选项对比表

安装环节 可选项 适用场景与说明
安装包类型 msi
zip
Docker
向导安装 / 便携版 / 容器化部署
服务账户 Network Service user
Local/Domain User
内置低权限 / 自定义权限,适合不同安全与企业环境需求
GUI 管理工具 MongoDB Compass 图形界面管理,适合不熟悉命令行的用户
安装验证 Windows 服务管理 确认 “MongoDB” 服务已安装、启动类型为“自动”

MongoDB配置文件

  • 配置文件类型

    • mongod.cfg(Windows 安装向导生成)
    • mongod.conf(Linux/macOS 原生,Windows 亦可)
  • 文件格式对比

    • Key-Value:安装程序生成,格式简单
    • YAML:官方推荐,结构清晰,便于维护
  • 常用配置项

    • systemLog:日志路径与方式
    • storage:数据目录与存储引擎
    • net:绑定 IP 与端口
    • security:开启授权认证
    • processManagement:守护进程与 PID 文件
  • 生效方式

    • 配置文件:mongod --config /path/to/mongod.conf
    • 命令行:--dbpath, --logpath, --bind_ip, --port, --auth
配置文件 默认平台 格式 适用场景
mongod.cfg Windows Key-Value 安装向导生成的简易配置
mongod.conf Linux/macOS(*) YAML 官方推荐,易于扩展维护
配置项 作用 常见字段示例
systemLog 日志输出位置与模式 destination, path
storage 数据目录与存储引擎选项 dbPath
net 网络绑定地址与监听端口 bindIp, port
security 用户认证与授权 authorization: enabled
processManagement 守护进程模式与 PID 文件 fork, pidFilePath

MongoDB相关工具

  • 官方工具

    • mongosh:命令行交互,脚本与自动化管理
    • Compass:GUI 可视化,拖拽式查询与分析
  • 第三方工具示例

    • Robo 3T / Studio 3T:增强型界面与导出功能
    • DbGate:跨 DB 多引擎统一管理
  • CLI 使用流程

    • 下载并解压或安装
    • 启动工具后输入连接字符串
    • 常用命令:show dbsuse <db>show collectionsdb.collection.insertOne()
工具名称 类型 主要用途
mongosh CLI 脚本化管理,自动化操作
Compass GUI 可视化数据浏览、查询与性能分析
Robo 3T GUI 轻量级图形界面,支持多种导出与插件
DbGate GUI/多引擎 多数据库统一管理,支持自定义查询与插件安装

MongoDB连接和启用认证

  • 连接字符串格式

    • mongodb://<user>:<pwd>@<host>:<port>/<db>?options
    • 特殊字符需 URL 编码(@ → %40/ → %2F: → %3A? → %3F
  • 常用选项

    • authSource、retryWrites、w、ssl、connectTimeoutMS、maxPoolSize…
  • 启用认证步骤

    • 在配置文件或启动参数中开启 authorization: enabled--auth
    • 用命令行连接到 admin 库,db.createUser(...) 创建管理员
    • 优雅停服:db.adminCommand({ shutdown: 1 }) 或系统服务命令
    • 重启带认证的服务,使用带凭证的连接字符串重新连接
步骤 方式 示例命令/字段
开启认证 配置文件 / 参数 security.authorization: enabled
--auth
创建管理员 mongosh use admin
db.createUser({...})
优雅关闭 mongosh / 系统服务 db.adminCommand({ shutdown: 1 })
net stop MongoDB
重启服务并连接 配置文件 / 参数 + URI mongod --config ...
mongodb://user:pwd@...

MongoDB的ObjectID

  • 定义与作用

    • 默认主键类型,12 字节 BSON,用于全局唯一标识文档
    • 十六进制字符串(24 字符)表现
  • 组成结构

    • 时间戳(4 字节):秒级 Unix 时间,保证排序性
    • 机器标识(3 字节):主机唯一哈希,区分节点
    • 进程 ID(2 字节):区分同机多进程生成
    • 随机计数器(3 字节):同时间内递增,防止冲突
  • 核心特性

    • 全局唯一性:组合信息确保不同环境无重复
    • 时间可提取:getTimestamp() 可还原创建时刻
    • 存储高效:仅 12 字节,比 UUID 更节省空间
  • 常见用法

    • 默认生成:插入文档时自动赋值
    • 查询筛选:find({ _id: ObjectId(...) })
    • 手动生成:var id = ObjectId()
    • 获取创建时间:ObjectId("…").getTimestamp()
组成部分 字节数 主要用途
时间戳 4 保证生成顺序与时间关联
机器标识 3 区分不同主机
进程 ID 2 区分同机不同进程
随机计数器 3 同秒内生成唯一性

MongoDB插入

  • insertOne(单条插入)

    • 语法:db.collection.insertOne(document, options)
    • 自动生成 _id(若未指定),或使用自定义 _id
    • 可选 writeConcernbypassDocumentValidation
    • 返回 { acknowledged: true, insertedId: <_id> }
  • insertMany(批量插入)

    • 语法:db.collection.insertMany([doc1, doc2, …], options)
    • 一次插入多条文档
    • 返回 { acknowledged: true, insertedIds: […] }
  • 冲突处理

    • 若指定的 _id 已存在,抛出 MongoServerError: E11000 duplicate key error
    • 可在应用层捕获并处理,或改用 upsert 等方式
  • insertOne vs. insertMany 对比

操作 场景 参数 返回值 注意事项
insertOne 单文档写入 document, options { acknowledged, insertedId } _id 自动/手动,冲突报错
insertMany 批量写入 Array<document>, options { acknowledged, insertedIds } 默认所有或全部失败(可配置)

MongoDB查询

MongoDB基础查询

  • 方法db.collection.find(query, projection)

  • 常见操作

    • 等于 $eq、不等 $ne、大于 $gt、小于 $lt、…
    • 字段存在 $exists、类型匹配 $type
  • 示例

    db.users.find({ age: { $gte: 25 } }, { name: 1 })
    
操作 语法 说明
等于 { age: 25 } age 精确匹配 25
范围查询 { age: { $gt:25, $lt:30 } } age 在 (25,30) 之间
字段存在 { score: { $exists:true } } 仅返回含有 score 字段的
类型匹配 { age: { $type:"int" } } age 必须为整数

MongoDB数组查询和嵌套字段查询

  • 数组查询

    • $in / $nin:包含或不包含指定元素
    • $elemMatch:数组中元素级条件
  • 嵌套字段

    • 点语法 "bag.index":value 或范围查询 { "bag.index":{ $gt:0 }}
db.users.find({ lessons:{ $in:[1,4] } })
db.users.find({ "bag.index":1 })
功能 操作符 作用
包含任一元素 { lessons:{ $in:[…] }} 数组含指定元素
排除某些元素 { lessons:{ $nin:[…] }} 数组不含指定元素
元素条件匹配 { lessons:{ $elemMatch:{ $gt:2 }}} 数组中存在大于 2 的元素
嵌套字段精确 { "bag.index":1 } 精确匹配子文档字段

MongoDB多条件查询

  • AND(隐式):多个字段同级条件
  • OR{ $or:[cond1,cond2] }
  • 复合:AND + $or
db.users.find({ age:25, $or:[{name:"T1"},{name:"T2"}] })
查询类型 语法 示例
AND { a:1, b:2 } 同时满足 a=1 且 b=2
OR { $or:[{a:1},{b:2}] } a=1 或 b=2
组合查询 { c:3, $or:[…] } c=3 且 (a=1 或 b=2)

MongoDB指定字段查询

  • Projection:第二参数 { field:1 } 包含,{ field:0 } 排除
  • **默认返回 _id**,可显式 { _id:0 }
  • 支持嵌套字段{ "bag.index":1 }
db.users.find({}, { name:1, age:1, _id:0 })
方式 语法 说明
包含字段 { name:1, age:1 } 仅返回 name 和 age
排除字段 { age:0 } 返回所有字段但不包括 age
排除 _id { _id:0 } 不返回 _id

MongoDB模糊查询

  • **正则 $regex**:字符串模式匹配
  • 忽略大小写$options:"i"
  • 常用模式^$.*[]|
db.users.find({ name:{ $regex:"^T", $options:"i" } })
场景 语法 说明
包含子串 { name:{ $regex:"Ta" }} 匹配包含 “Ta”
开头匹配 { name:{ $regex:"^T" }} 以 T 开头
结尾匹配 { name:{ $regex:"2$" }} 以 2 结尾
忽略大小写 { name:{ $regex:"t", $options:"i" }} 不区分大小写

MongoDB排序查询

  • **.sort({ field:1|-1 })**:1 升序,-1 降序
  • 支持多字段:按字段顺序依次排序
db.users.find().sort({ age:1, name:-1 })
排序方式 语法 说明
单字段升序 { age:1 } age 从小到大
单字段降序 { age:-1 } age 从大到小
多字段排序 { age:1, name:-1 } age 再 name

MongoDB分页查询

  • **skip(n).limit(m)**:跳过 n,取 m 条
  • 游标分页{ _id:{ $gt:lastId }} + limit
  • 排序分页:结合 .sort() + skip/limit
db.users.find().skip(10).limit(5)
db.users.find({ _id:{ $gt:objId } }).limit(5)
方法 优缺点 用例
skip/limit 简单;大量 skip 性能差 小数据量分页
游标分页 高效;依赖递增键;不支持随机页 大数据集连续翻页
排序分页 指定顺序,结合 skip/limit 使用 需按特定字段分页

MongoDB聚合查询概念

  • Aggregation Pipeline:管道阶段数组
  • 每阶段输入→处理→输出
  • 典型阶段$match, $group, $sort, $limit, $project

MongoDB过滤文档聚合查询

  • **$match**:在管道中做过滤
  • find 条件一致,但可与后续阶段组合
db.collection.aggregate([ { $match:{ age:{ $gt:25 } } } ])
操作符 用途 示例
$match 文档过滤 { $match:{ status:"A" } }

MongoDB分组聚合查询

  • **$group**:类似 SQL GROUP BY
  • _id 定义分组键,可用聚合表达式计算
  • 常用累加器$sum,$avg,$max,$min,$push,$addToSet
db.sales.aggregate([
  { $group:{ _id:"$item", total:{ $sum:"$quantity" } } }
])
累加器 功能 示例
$sum 求和 { totalQty:{ $sum:"$qty" } }
$avg 平均值 { avgPrice:{ $avg:"$price" } }
$push 收集为数组 { allQty:{ $push:"$qty" } }

MongoDB排序聚合查询

  • **$sort**:管道内排序
  • 用法同 .sort()
db.students.aggregate([ { $sort:{ score:-1, age:1 } } ])
排序符号 含义
1 升序
-1 降序

MongoDB分页聚合查询

  • **$skip + $limit**:管道内分页
  • $sort 再跳过再限制
db.students.aggregate([
  { $sort:{ age:1 } },
  { $skip:5 },
  { $limit:5 }
])
阶段 描述
$skip 跳过指定文档数
$limit 限制返回文档数

MongoDB索引

索引概念

  • 用于加速查询,基于 B-tree 结构
  • 全表扫描 → 索引查询:查找复杂度从 O(n) 降至 O(log n)
  • 建立索引会增加存储空间和写入开销,需权衡查询性能与写入成本

单字段索引

  • 针对单个字段创建升序(1)或降序(−1)索引
  • 语法:db.coll.createIndex({ field: 1 })
  • 自动应用于 _id 字段,用户可自定义,如 { age: 1 }
  • 支持覆盖索引:仅访问索引即可返回结果

复合索引

  • 多字段组合索引,字段顺序决定前缀匹配能力
  • 语法:db.coll.createIndex({ a:1, b:-1 })
  • 优化多字段查询与排序
  • 只能利用最左前缀,如索引 {a,b,c} 能加速查询 {a,…}{a,b,…}{a,b,c}

文本索引

  • 全文搜索,跨多字段,用于$text查询
  • 语法:db.coll.createIndex({ title:"text", content:"text" })
  • 支持短语搜索、排除词(-word)、相关性评分、权重设置
  • 支持多语言与自定义停用词

哈希索引

  • 基于字段值的哈希,适合等值查询
  • 语法:db.coll.createIndex({ key:"hashed" })
  • 不支持范围查询或排序,只用于精确匹配

地理空间索引

  • 2d:平面坐标(XY)索引;2dsphere:球面(经纬度)索引
  • 语法:db.coll.createIndex({ loc:"2dsphere" })
  • 支持 $near$geoWithin$centerSphere 等地理查询

稀疏索引

  • 仅索引包含该字段的文档,忽略字段缺失文档
  • 语法:db.coll.createIndex({ f:1 }, { sparse:true })
  • 节省空间,适合字段偶尔存在场景
  • 与唯一索引结合可对部分文档做唯一约束

唯一索引

  • 保证索引字段值或字段组合唯一
  • 语法:db.coll.createIndex({ email:1 }, { unique:true })
  • 防止重复数据,可在单字段或复合字段上应用

部分索引

  • 基于 partialFilterExpression 只为符合条件的文档建索引
  • 语法:db.coll.createIndex({ f:1 }, { partialFilterExpression:{ status:"A" } })
  • 更灵活替代稀疏索引,节省空间并优化特定查询

操作对比

索引类型 创建语法 适用场景 支持特点 限制
单字段索引 { field:1 } 单字段查询、排序 覆盖索引 写入开销、所有文档均有索引条目
复合索引 { a:1, b:-1 } 多字段筛选与排序 前缀匹配 字段顺序敏感
文本索引 { f:"text", g:"text" } 全文搜索、短语、相关性排序 多字段、权重、多语言、停用词 字段类型限于字符串
哈希索引 { field:"hashed" } 精确值查询 等值查找高效 不支持范围/排序
地理空间索引 { loc:"2d" } / { loc:"2dsphere" } 位置搜索、地图应用 支持多种地理操作符 数据格式需 GeoJSON 或平面坐标
稀疏索引 { f:1 }, { sparse:true } 字段偶尔存在、减少无用索引条目 只索引存在字段的文档 不索引缺失字段文档
唯一索引 { f:1 }, { unique:true } 防止重复值 单字段或复合字段唯一性 创建前需清理重复数据
部分索引 { f:1 }, { partialFilterExpression: {...} } 特定条件优化 灵活过滤条件 仅对符合条件文档索引

MongoDB更新

首条更新 (updateOne)

  • 针对匹配的第一条文档执行更新
  • 使用更新操作符:$set(设置/新增字段)、$inc(增减数值)、$unset(删除字段)等
  • 支持 upsert:true(无匹配时插入新文档)
  • 常见选项:writeConcern(写入确认)、collation(排序规则)

多条更新 (updateMany)

  • 针对所有匹配文档批量执行更新
  • 同样使用更新操作符,可组合多种如 $set$unset$inc
  • 支持 upsertarrayFilters(针对嵌套数组元素)、hint(指定索引)
  • 适用于:批量状态修改、计数器更新、数据清理

替换更新 (replaceOne)

  • 完整新文档替换匹配的第一条文档
  • 替换文档必须包含所有必需字段(尤其是 _id
  • 不能使用 $ 操作符,选项支持 upsertcollationwriteConcern
  • 适用于:需要保证文档结构一致、一次性覆盖所有字段的场景

操作对比

操作 更新范围 使用方式 文档保留 支持 Upsert 覆盖方式
updateOne 第一条匹配文档 使用更新操作符(如 $set, $inc 只改动指定字段 局部字段更新
updateMany 所有匹配文档 updateOne 只改动指定字段 局部字段更新
replaceOne 第一条匹配文档 提供完整替换文档(无更新操作符) 删除未包含字段 整个文档被新文档覆盖

MongoDB删除

deleteOne

  • 删除匹配的第一条文档
  • 语法:db.collection.deleteOne(filter, { collation })
  • 不返回被删文档
  • 只会删除第一个符合条件的,操作不可撤销

deleteMany

  • 删除所有匹配文档
  • 语法:db.collection.deleteMany(filter, { collation })
  • 不返回被删文档
  • 留空条件 ({}) 会清空整个集合

findOneAndDelete

  • 查找并删除第一条匹配文档,同时返回它
  • 语法:db.collection.findOneAndDelete(filter, { sort, projection, collation })
  • 返回被删文档,便于后续处理
  • 可配合 sort 决定优先删除哪条

drop

  • 删除整个集合及其索引
  • 语法:db.collection.drop()
  • 一次性移除集合,无法恢复

remove (弃用)

  • 旧版删除方法,不推荐
  • 语法:db.collection.remove(filter, { justOne })
  • 功能已被 deleteOne/deleteMany 取代

操作对比

操作 删除范围 返回被删文档 典型场景
deleteOne 第一条匹配文档 删除某个条件下的单条记录
deleteMany 所有匹配文档 批量清理符合条件的数据
findOneAndDelete 第一条匹配文档 删除并需要获取被删文档(审计/日志)
drop 整个集合 清理整个集合及其索引
remove (弃用) 单条或多条(取决于 justOne 旧版代码兼容,建议迁移至新 API

MongoDB联动C#

C#操作MongoDB

驱动安装

  • 推荐通过 NuGet 安装 MongoDB.Driver,升级更便捷
  • 也可从 GitHub 获取源代码,适合自定义需求

连接与模型

  • MongoClient("mongodb://…") 重用单例,线程安全
  • GetDatabaseGetCollection<T> 动态映射库与集合
  • C# 类加上 [BsonId][BsonRepresentation][BsonElement] 与字段一一对应

CRUD 操作

操作 API 说明
插入 InsertOne / InsertMany 同步插入单个或多个文档
查询 Find(filter).ToList() 支持 Lambda 表达式和 Builders
更新 UpdateOne(filter, update) $set$inc 等操作符,支持 upsert
替换 ReplaceOne(filter, replacement) 整文档替换
删除 DeleteOne / DeleteMany 精确条件删除单条或多条
索引 Indexes.CreateOne(new CreateIndexModel…) 为常用查询字段创建 B-Tree 索引

使用建议

  • 为高频查询字段建索引
  • 整个应用复用单个 MongoClient
  • 捕获 MongoException 并记录,保证健壮性

C#使用Bson操作MongoDB

BSON 文档构建与插入

  • var doc = new BsonDocument { … } 支持嵌套 BsonDocumentBsonArray
  • collection.InsertOne(doc)

BSON 查询与筛选

var all = collection.Find(new BsonDocument()).ToList();
var filtered = collection.Find(new BsonDocument("age", new BsonDocument("$gt", 25))).ToList();

BSON 更新与删除

操作 调用示例
更新 collection.UpdateOne( new BsonDocument("name","John"), new BsonDocument("$set", new BsonDocument("age",35)) )
删除 collection.DeleteOne( new BsonDocument("name","John") )

BSON 索引

collection.Indexes.CreateOne(new CreateIndexModel<BsonDocument>(new BsonDocument("name",1)));

要点

  • 直接操作 BsonDocument,更灵活但少了类型安全
  • 适合动态结构或快速原型
  • 与强类型 API 可混合使用,按需选择


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏