MongoDB - 增删改查

打印 上一主题 下一主题

主题 689|帖子 689|积分 2071

连接

标准 URI 连接语法

通常,可以设定标准的 URI 连接语法,作为连接配置:
  1. mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
复制代码

  • mongodb://: 固定的格式,即指定当前的 URI 是标准的 MongoDB 连接语法
  • username:password@: 可选项,如果设置,在连接数据库服务器之后,驱动会尝试登录这个数据库
  • host1: 必须的,至少指定一个 host,它指定了要连接服务器的地址。如果要连接副本及集,需要指定多个主机地址
  • portX: 可选的指定端口,如果不填,默认为 27017
  • /database: 如果指定账号和密码,连接并验证登录指定数据库。若不指定,默认打开 test 数据库
  • ?options: 连接选项,如果没有指定数据库,则前面需要加上 /。所有连接选项都是键值对 name=value,键值对之间通过 & 或 ; 隔开
连接选项

标准的连接格式包含了多个选项,如下所示:

  • replicaSet=name: 验证副本集的名称
  • slaveOk=true|false: 选择连接主服务器的方式

    • true: 表示有从服务器,当 connect=direct 时会连接第一台机器,即使这台不是主服务器;当 connect=replicaSet 时会发送所有的写请求到主并且把读请求分布在其他从服务器
    • false: 表示无从服务器,当 connect=direct 时会自动找寻主服务器;当 connect=replicaSet 时仅连接主服务器,并且所有的读写命令都连接到主服务器

  • safe=true|false: 设置为 true 时,在执行更新操作之后,驱动都会发送 getLastError 命令来确保更新成功
  • w=n: 驱动添加 {w: n} 到 getLastError 命令,应用于 safe=true
  • wtimeoutMS=ms: 驱动添加 {wtimeout: ms} 到 getLastError 命令,应用于 safe=true
  • fsync=true|false: 驱动添加 {fsync: true} 到 getLastError 命令,应用于 safe=true
  • journal=true|false: 如果设置为 true,同步到日志(在提交到数据库前写入到实体中),应用于 safe=true
  • connectTimeoutMS=ms: 可以打开连接的时间
  • socketTimeoutMS=ms: 发送和接受 socket 的时间
连接命令格式

使用 mongosh 连接 MongoDB 时,也支持命令选项的方式添加配置:

  • --host arg: 指定数据库地址
  • --port arg: 指定数据库端口
  • -u [ --username ] arg: 鉴权的账号
  • -p [ --password ] arg: 鉴权的密码
插入文档

插入校验

MongoDB 会对要插入的数据进行最基本的检查:检查文档的基本结构,如缺少 _id 键会自动添加一个、是否包含非 UTF-8 字符、是否使用了无法识别的类型、检查文档大小等。
其中,检查文档大小主要因为 MongoDB 限制了所有文档必须小于 16MB,主要是为了防止不良的模式设计并确保性能上的一致。
要查看文档的 BSON 大小,可以在 shell 中执行 Object.bsonsize(doc) 查看字节大小。
单个插入

官方文档:db.collection.insertOne() — MongoDB Manual
  1. db.collection.insertOne(
  2.     <document>,
  3.     {
  4.         writeConcern: <document>
  5.     }
  6. )
复制代码
批量插入

官方文档:db.collection.insertMany() — MongoDB Manual
  1. db.collection.insertMany(
  2.     [ <document 1> , <document 2>, ... ],
  3.     {
  4.         writeConcern: <document>,
  5.         ordered: <boolean>
  6.      }
  7. )
复制代码
通过传输 ordered=true 可以确保文档按提供的顺序插入,指定为 false 则允许 MongoDB 重新排列插入的顺序以提高性能,默认为 true 值。
以有序插入的方式使用 insertMany 出现错误将会阻塞后续的插入动作,无需插入的方式则不管其他插入是否出现了错误。
删除文档

单个删除

官方文档:db.collection.deleteOne() — MongoDB Manual
  1. db.collection.deleteOne(
  2.     <filter>,
  3.     {
  4.          writeConcern: <document>,
  5.          collation: <document>,
  6.          hint: <document|string>    // Available starting in MongoDB 4.4
  7.     }
  8. )
复制代码
使用 hint 参数可以指定 filter 查询时命中的索引,这对于复杂的索引结构时可以提升部分效率。
批量删除

官方文档:db.collection.deleteMany() — MongoDB Manual
  1. db.collection.deleteMany(
  2.     <filter>,
  3.     {
  4.          writeConcern: <document>,
  5.          collation: <document>,
  6.          hint: <document|string>    // Available starting in MongoDB 4.4
  7.     }
  8. )
复制代码
单个删除并返回

官方文档:db.collection.findOneAndDelete() — MongoDB Manual
  1. db.collection.findOneAndDelete(
  2.     <filter>,
  3.     {
  4.         writeConcern: <document>,
  5.         projection: <document>,
  6.         sort: <document>,
  7.         maxTimeMS: <number>,
  8.         collation: <document>
  9.     }
  10. )
复制代码
更新文档

更新文档是原子操作:如果两个更新同时发生,那么首先到达服务器的更新会先被执行,然后再执行下一个更新。
因此,相互冲突的更新可以安全地迅速接连完成,而不会破坏任何文档:最后一次更新将“成功”。如果不想使用默认行为,则可以考虑使用文档版本控制模式。
单个更新

官方文档:db.collection.updateOne() — MongoDB Manual
  1. db.collection.updateOne(
  2.     <filter>,
  3.     <update>,
  4.     {
  5.         upsert: <boolean>,
  6.         writeConcern: <document>,
  7.         collation: <document>,
  8.         arrayFilters: [ <filterdocument1>, ... ],
  9.         hint:  <document|string>    // Available starting in MongoDB 4.2.1
  10.     }
  11. )
复制代码
在更新文档的时候,比较需要注意的事 upsert 的使用,其是一种特殊类型的更新:如果找不到与筛选条件相匹配的文档,则会以这个条件和更新文档为基础来创建一个新文档;如果找到了匹配的文档,则进行正常的更新。
因此,使用 upsert 的好处就是,可以使用同一套代码创建和更新文档。
使用 upsert 时就涉及到一个 $setOnInsert 运算符,它的作用是,只会在插入文档时设置字段的值,在后续的更新时不对其进行更改。
批量更新

官方文档:db.collection.updateMany() — MongoDB Manual
  1. db.collection.updateMany(
  2.     <filter>,
  3.     <update>,
  4.     {
  5.         upsert: <boolean>,
  6.         writeConcern: <document>,
  7.         collation: <document>,
  8.         arrayFilters: [ <filterdocument1>, ... ],
  9.         hint:  <document|string>    // Available starting in MongoDB 4.2.1
  10.     }
  11. )
复制代码
单个替换

官方文档:db.collection.replaceOne() — MongoDB Manual
  1. db.collection.replaceOne(
  2.     <filter>,
  3.     <replacement>,
  4.     {
  5.         upsert: <boolean>,
  6.         writeConcern: <document>,
  7.         collation: <document>,
  8.         hint: <document|string>     // Available starting in 4.2.1
  9.     }
  10. )
复制代码
replaceOne 和 updateOne 操作的区别在于,updateOne 可以更新文档中部分键的值,而 replaceOne 的作用是直接将整个文档都替换掉,通常是建议使用 updateOne 而不是 replaceOne。
单个更新并返回

官方文档:db.collection.findOneAndUpdate() — MongoDB Manual
  1. db.collection.findOneAndUpdate(
  2.     <filter>,
  3.     <update document or aggregation pipeline>,  // Changed in MongoDB 4.2
  4.     {
  5.         projection: <document>,
  6.         sort: <document>,
  7.         maxTimeMS: <number>,
  8.         upsert: <boolean>,
  9.         returnDocument: <string>,
  10.         returnNewDocument: <boolean>,
  11.         collation: <document>,
  12.         arrayFilters: [ <filterdocument1>, ... ]
  13.     }
  14. )
复制代码
使用 findOneAndUpdate 而不是 updateOne 的最大目的莫过于使用 findOneAndUpdate 可以返回更新前后文档内容。
通过设置 returnNewDocument 的值为 true 可以返回更新后的文档,为 false 时可以返回更新前的文档。
单个替换并返回

官方文档:db.collection.findOneAndReplace() — MongoDB Manual
  1. db.collection.findOneAndReplace(
  2.     <filter>,
  3.     <replacement>,
  4.     {
  5.         projection: <document>,
  6.         sort: <document>,
  7.         maxTimeMS: <number>,
  8.         upsert: <boolean>,
  9.         returnDocument: <string>,
  10.         returnNewDocument: <boolean>,
  11.         collation: <document>
  12.     }
  13. )
复制代码
更新运算符

官方文档:Update Operators — MongoDB Manual
对于如 updateOne、updateMany、findOneAndUpdate 等更新操作,MongoDB 提供了原子的更新运算符支持只更新部分数据。
运算符支持以 { : { : ,... } } 的方式使用,并且可以同时使用多个运算符。
为避免出现歧义,不建议对同一个属性同时使用不同的运算符。
字段


  • $currentDate: 将指定键设置为当前时间
  • $inc: 对数字类型的键做递增操作
  • $min: 会比较原始值和更新值,并设置成较小值
  • $max: 会比较原始值和更新值,并设置成较大值
  • $mul: 对数字类型的键做乘法操作
  • $rename: 修改指定键的名称
  • $set: 将指定键设置为指定值
  • $setOnInsert: 与 upsert 配合使用,如果更新导致文档插入,则设置字段的值,对修改现有文档的更新操作无效
  • $unset: 删除指定键
数组


  • $: 充当占位符,更新与查询条件匹配的第一个元素
  • $[]: 充当占位符,为匹配查询条件的文档更新数组中的所有元素
  • $[]: 充当占位符,为匹配查询条件的文档更新与 arrayFilters 条件匹配的所有元素
  • $addToSet: 仅当集合中不存在该元素时,才将元素添加到数组中
  • $pop: 传 { $pop: { field: 1 } } 表示删除数组中的最后一项,传 -1 时表示删除第一项
  • $pull: 删除与指定查询匹配的所有数组元素
  • $push: 新增一项到数组中
  • $pullAll: 删除列出的所有数组元素
数组内层


  • $each: 使用 $push 或 $addToSet 运算符时,增加此运算符可以批量添加元素
  • $position: 与 $each 配合使用,可以指定添加元素的位置
  • $slice: 与 $each 配合使用,防止数组的增长超过某个大小,传正数表示从左到右截断
  • $sort: 与 $each 配合使用,对添加完元素的数组进行排序
位运算

$bit: 支持对整数值进行按位 AND、OR 或 XOR 更新,通过使用 { $bit: { : { :  } } } 完成更新。
批量写操作

官方文档:db.collection.bulkWrite() — MongoDB Manual
MongoDB 提供了 bulkwrite 命令支持批量执行命令,批处理时在一定程度上减少了网络交互的损耗。
  1. db.collection.bulkWrite(
  2.     [ <operation 1>, <operation 2>, ... ],
  3.     {
  4.          writeConcern: <document>,
  5.          ordered: <boolean>
  6.     }
  7. )
复制代码
支持的以下操作:

  • insertOne
  • updateOne
  • updateMany
  • replaceOne
  • deleteOne
  • deleteMany
查询文档

单个查询

官方文档:db.collection.findOne() — MongoDB Manual
  1. db.collection.findOne(query, projection, options)
复制代码
第一个参数是查询条件,可以使用键值对的方式指定需要匹配的条件,多个键之间是 AND 的关系。
第二个参数用于仅返回指定的键,既可以节省网络传输的数据量,也可以减少客户端解码文档的时间和内存消耗。
第三个参数可以指定查询到可选项,这些选项会修改查询行为和返回结果的方式。更多查看 官方文档
批量查询

官方文档:db.collection.find() — MongoDB Manual
  1. db.collection.find(query, projection, options)
复制代码
数据库会使用游标返回 find 的执行结果。
对于游标,客户端可以限制结果的数量,跳过一些结果,按任意方向的任意键组合对结果进行排序等操作。更多查询 官方文档
下述是一些常用的游标方法:

  • count(): 统计游标引用的文档数量
  • hasNext(): 查询是否有下一个结果
  • hint(index): 指定游标命中的索引
  • limit(number): 限制返回结果的数量
  • next(): 返回下一个搜索结果
  • size(): 返回应用 skip() 和 limit() 之后的查询数量
  • skip(number): 控制跳过一定的数量,跳过大量数据会比较慢
  • sort(sort): 使用键值对的方式对搜索结果进行排序
在服务器端,游标会占用内存的资源。通常在以下情况会终止游标及进行随后的清理:

  • 当游标遍历完成匹配的结果时,它会清除自身
  • 当游标超出客户端的作用域时,驱动程序会向数据库发送终止游标的信号
  • 当游标达到 10 分钟没有使用时,数据库游标会被自动销毁
查询运算符

官方文档:Query and Projection Operators — MongoDB Manual
同样的,设置查询条件时,MongoDB 提供了查询运算符支持更多的查询方式。
比较运算符


  • $eq: 返回等于指定值的结果,等同 { :  } 的显式表示
  • $gt: 返回大于指定值的结果
  • $gte: 返回大于等于指定值的结果
  • $in: 返回等于指定数组中任意一个值的结果,对于一个键匹配多个值,$in 比 $or 更方便
  • $lt: 返回小于指定值的结果
  • $lte: 返回小于等于指定值的结果
  • $ne: 返回不等于指定值的结果
  • $nin: 返回不等于指定数组中任意一个值的结果
逻辑运算符


  • $and: 返回同时符合查询子句要求的结果
  • $not: 元运算符,匹配不符合查询语句要求的结果
  • $nor: 返回不能同时符合查询子句要求的结果
  • $or: 返回与任意一个查询子句的条件匹配的结果
对于普通的 $and 类型查询,我们总是希望尽可能用最少的参数来限定结果的范围。而 $or 类型查询则相反,如果第一个参数能够匹配尽可能多的文档,则其效率最高。
元素运算符


  • $exists: 判断指定键是否存在,返回符合要求的结果
  • $type: 判断指定键的数据类型,返回符合要求的结果(好的模式设计不应该出现不同类型)
表达式运算符


  • $expr: 允许使用聚合表达式,适合用在一些比较复杂的查询语句
  • $jsonSchema: 根据给定的 JSON 模式验证文档,返回符合要求的结果
  • $mod: 指定键的值执行模运算,返回符合要求的结果
  • $regex: 使用正则表达式对指定键做匹配,MongoDB 可以利用索引来查询前缀正则表达式,但不能用于不区分大小写的搜索
  • $text: 对使用文本索引的字段内容执行文本搜索,可以作为一个简易的搜索引擎使用
  • $where: 允许在查询时执行任意 JavaScript 代码(性能较差,尽可能使用 $expr 代替)
数组运算符


  • $all: 匹配包含查询中指定的所有元素的数组
  • $elemMatch: 用于强制将查询子句与单个数组元素进行匹配
  • $size: 匹配指定数组长度大小的结果
投影运算符

投影运算符针对的是查询语句的第二个参数,即返回的结果。

  • $: 仅返回数组中与查询条件匹配的第一个元素
  • $elemMatch: 对返回结果中的数组元素做 $elemMatch 匹配,仅返回数组中满足要求的元素
  • $meta: 与 $text 运算符配合使用,返回与文档关联的元数据,可以返回匹配分数,或者索引键
  • $slice: 对返回结果中的数组做截取返回
特殊的 null 值

在 MongoDB 中,null 是一个比较特殊的值,它可以与自身匹配。也就是说了,通过 { field: null } 可以查询出 field 键为 null 的文档。
不过,更特殊的是,null 同样会匹配缺少这个键值的文档。也就是说,{ field: null } 可以查询出不包含 field 键的文档。
如果仅想匹配键值为 null 的文档,则需要检查该键的值是否为 null,并且通过 $exists 条件确认该键已存在,如 { field: { $eq: null, $exists: true } } 就是这样的查询条件组。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表