MongoDB:14-MongoDB- 原子操作

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: MongoDB:14-MongoDB- 原子操作


  1. Redis采用的是异步I/O非阻塞的单进程模型,每一条Redis命令都是原子性的。
  2. 那么mongoDB呢? mongo有哪些原子操作呢?有哪些实现事务性操作的技巧呢?


MongoDB 原子操作


  1. mongodb不支持事务,所以,在你的项目中应用时,要注意这点。无论什么设计,都不要要求mongodb保证数据的完整性。
  2. 但是mongodb提供了许多原子操作,比如文档的保存,修改,删除等,都是原子操作。
  3. 所谓原子操作就是要么这个文档保存到Mongodb,要么没有保存到Mongodb,不会出现查询到的文档没有保存完整的情况。




原子操作数据模型


  • 考虑下面的例子,图书馆的书籍及结账信息。
  • 实例说明了在一个相同的文档中如何确保嵌入字段关联原子操作(update:更新)的字段是同步的


  1. book = {
  2.          _id: 123456789,
  3.          title: "MongoDB: The Definitive Guide",
  4.          author: [ "Kristina Chodorow", "Mike Dirolf" ],
  5.          published_date: ISODate("2010-09-24"),
  6.          pages: 216,
  7.          language: "English",
  8.          publisher_id: "oreilly",
  9.          available: 3,
  10.          checkout: [ { by: "joe", date: ISODate("2012-10-15") } ]
  11.        }


  • 你可以使用 db.collection.findAndModify() 方法来判断书籍是否可结算并更新新的结算信息
  • 在同一个文档中嵌入的 available 和 checkout 字段来确保这些字段是同步更新的:



  1. db.books.findAndModify ( {
  2.   query: {
  3.            _id: 123456789,
  4.            available: { $gt: 0 }
  5.          },
  6.   update: {
  7.             $inc: { available: -1 },
  8.             $push: { checkout: { by: "abc", date: newDate() } }
  9.           }
  10. } )
  11. 拥有类似事务特性的更新与查询操作——findAndModify.

  12. 它是原子性的,会返回符合查询条件的更新后的文档。

  1. db.COLLECTION_NAME.findAndModify({query:{},
  2.                                 update:{},
  3.                                 remove:true|false,
  4.                                 new:true|false,
  5.                                 sort:{},
  6.                                 fields:{},
  7.                                 upsert:true|false});
  • query是查询选择器,与findOne的查询选择器相同
  • update是要更新的值,不能与remove同时出现
  • remove表示删除符合query条件的文档,不能与update同时出现
  • newtrue:返回个性后的文档,false:返回个性前的,默认是false
  • sort:排序条件,与sort函数的参数一致。
  • fields:投影操作,与find*的第二个参数一致。
  • upsert:与updateupsert参数一样。
  1. 不论是update的第二个参数,还是findAndModify的update,在不指定更新操作符的情况下,将会用指定的新值替换旧值。
  2. 比如,
  1. use iteye;
  2. db.blog.update({_id:ObjectId('......')},{title:'new title'});

  1. //上面的操作就把指定_id的文档的标题改成了‘new title’
  • 如果指定了更新操作符,就可以实现更复杂灵活的更新操作。
  • 可以通过更新操作符,增加或减少数值,针对数组类型的属性,做类似队列或栈的操作。
  • 单从这一点来说,mongo要比sql数据库强大的多了。




原子操作常用命令(更新操作符)


  • $set
  • 用来指定一个键并更新键值,若键不存在并创建。


  1.  用"$set"甚至可以修改键的数据类型
  1. db.users.insert({"name":"egger", "age": 28, "sex" : "male"})
  2. db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},{"$set" : {"sex" :1 }} )

  1. { $set : { field : value } }
  1. 使用"$set"修改内嵌文档:
  2. db.posts.update({"author.name":"egger"},{"$set":{"author.name":"mongo","author.age":18}})


  • $unset
  • 用来删除一个键。
  1. { $unset : { field : 1} }


  • $inc
  • $inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。
  1. 负数,表示减少
  2. "$inc"只能用于整数、长整数或双精度浮点数。要是用在其他类型的数据上就会导致操作失败。
  3. { $inc : { field : value } }
  • upsert
  1. upsert是一种特殊的更新操作,不是一个操作符。(upsert = up[date]+[in]sert)
  2. update() 方法的三个参数是upsert,这个参数是个布尔类型,默认是false
  3. 当它为true的时候,update方法会首先查找与第一个参数匹配的记录,在用第二个参数更新之,
  4. 如果找不到与第一个参数匹配的的记录,
  5. 就会以这个条件和更新文档为基础创建一个新的文档。如果找到了匹配的文档,则正常更新。
  6. upsert非常方便,不必预置集合,同一方法可以既创建又更新文档。

  • $setOnInsert
  1. 当update方法使用upsert选项执行insert操作时,$setOnInsert操作符给相应的字段赋值。类似sql中update 语句的set。
  1. db.collection.update( <query>,
  2.                      { $setOnInsert: { <field1>: <value1>, ... } },
  3.                      { upsert: true }   //{ upsert: true }可以用true替换
  4.                    )


  • $(query)
  1. $ (query)
  1. 语法: { "<array>.$" : value }
  2.  当对数组字段进行更新时,且没有明确指定的元素在数组中的位置,
  3.  我们使用定位操作符("$")标识一个元素,数字都是以0开始的。
  4.   
  5. 和update()一起使用:

  1. 定位操作符("$")作为第一个匹配查询条件的元素的占位符,也就是在数组中的索引值。
  2. 数组字段必须出现查询文档中。
  3.   集合students中有两条文档:
  1. { "_id" : 1, "grades" : [ 78, 88, 88 ] }
  2. { "_id" : 2, "grades" : [ 88, 90, 92 ] }
  1.   执行下列语句创建集合文档数据:
  1. db.students.remove();
  2. db.students.insert({ "_id" : 1, "grades" : [ 78, 88, 88 ] });
  3. db.students.insert({ "_id" : 2, "grades" : [ 88, 90, 92 ] });

  1.   执行下列操作:
  2. //查询匹配的文档中,数组有2个88,只更新第一个匹配的元素,也就是"grades.1"
  1. db.students.update( { _id: 1, grades: 88 }, { $set: { "grades.$" : 82 } }) ;

  1. //查询文档中没有出现grades字段,查询报错
  1. db.students.update( { _id: 2 }, { $set: { "grades.$" : 82 } } );


  • $push
  • 用法:
  1. { $push : { field : value } }
  1. 把value追加到field里面去,field一定要是数组类型才行,如果field不存在,会新增一个数组类型加进去。
  • $pushAll
  • 同$push,只是一次可以追加多个值到一个数组字段内。
  1. { $pushAll : { field : value_array } }

  • $pull
  • 从数组field内删除一个等于value值。
  1. 语法:db.collection.update( { field: <query> }, { $pull: { field: <query> } } );
  2. { $pull : { field : _value } }
  3. //插入一条文档
  4. db.profiles.insert({ votes: [ 3, 5, 6, 7, 7, 8 ] });
  5. //移除数组中所有元素7
  6. db.profiles.update( { votes: 3 }, { $pull: { votes: 7 } } );
  7. //移除数组中所有大于6的元素
  8. db.profiles.update( { votes: 3 }, { $pull: { votes: { $gt: 6 } } } );
  9. //Result
  10. { votes: [ 3, 5, 6, 8 ] }
  11. { votes: [ 3, 5, 6 ] }



  • $addToSet


  • 增加一个值到数组内,而且只有当这个值不在数组内才增加。


  • $pop
  • 删除数组的第一个或最后一个元素
  1. { $pop : { field : 1 } }



  • $rename
  • 修改字段名称
  1. $rename操作符可以重命名字段名称,新的字段名称不能和文档中现有的字段名相同。
  2. 如果文档中存在A、B字段,将B字段重命名为A,$rename会将A字段和值移除掉,然后将B字段名改为A.
  3.  当重命名子文档字段名时需要使用"."操作符,格式:值为该子文档的字段名.子文档中字段名。
  1. $rename操作符也可以将子文档中键值移到其他子文档中。
  1. db.students.update( { _id: 1 }, { $rename: { "name.last": "contact.lname" } } )
  1. 我们将名为name的子文档中的last字段,重名为“lname”,同时将其移动到子文档contact中,
  2. 若contact字段不存在,数据库会新建该字段。

  1. { $rename : { old_field_name : new_field_name } }
  2. 若指定的字段在集合中不存在,$rename操作符将不会有任何影响。
  1. db.students.update( { _id: 1 }, { $rename: { 'wife': 'spouse' } } )
  2.   若指定的多个字段在集合中都不存在,$rename操作符将不会有任何影响。
  3. db.students.update( { _id: 1 }, { $rename: { 'wife': 'spouse', 'vice': 'vp',  'office': 'term' } } )
  4.   集合中不存在上面语句中指定的wife、vice、office字段,所以上述的更新操作无任何影响。

  1. 若指定的多个字段中,有的在集合中存在,有的不存在,$rename操作符执行下列操作:
  1. 存在的字段按照上面的规则重命名为新的名称。
  2. 不存在的字段对数据无任何影响。



  • $bit
  • 位操作,integer类型
  1. {$bit : { field : {and : 5}}}


  • 偏移操作符
  1. > t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] }
  2. > t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true )
  3. > t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
  4. update() 方法
  5. update() 方法用于更新已存在的文档。语法格式如下:
  1. db.collection.update(
  2.   <query>,
  3.   <update>,
  4.   {
  5.     upsert: <boolean>,
  6.     multi: <boolean>,
  7.     writeConcern: <document>
  8.   }
  9. )

  1. 参数说明:
  1. query : update的查询条件,类似sql update查询内where后面的。
  2. update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
  3. upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  4. multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  5. writeConcern :可选,抛出异常的级别。

参考来源: http://www.runoob.com/mongodb/mongodb-atomic-operations.html


相关文章
|
12月前
|
NoSQL MongoDB
MongoDB 原子操作
10月更文挑战第21天
78 2
|
监控 NoSQL 安全
MongoDB 原子操作:确保数据一致性和完整性的关键
MongoDB 原子操作:确保数据一致性和完整性的关键
284 0
|
NoSQL MongoDB
​​​软件开发入门教程网之​​MongoDB 原子操作
本章将会讲解mongodb不支持事务,所以,在你的项目中应用时,要注意这点。无论什么设计,都不要要求mongodb保证数据的完整性。
​​​软件开发入门教程网之​​MongoDB 原子操作
|
NoSQL MongoDB
开心档-软件开发入门之MongoDB 原子操作
【摘要】 本章将会讲解mongodb不支持事务,所以,在你的项目中应用时,要注意这点。无论什么设计,都不要要求mongodb保证数据的完整性。
|
3月前
|
NoSQL MongoDB 数据库
数据库数据恢复—MongoDB数据库数据恢复案例
MongoDB数据库数据恢复环境: 一台操作系统为Windows Server的虚拟机上部署MongoDB数据库。 MongoDB数据库故障: 工作人员在MongoDB服务仍然开启的情况下将MongoDB数据库文件拷贝到其他分区,数据复制完成后将MongoDB数据库原先所在的分区进行了格式化操作。 结果发现拷贝过去的数据无法使用。管理员又将数据拷贝回原始分区,MongoDB服务仍然无法使用,报错“Windows无法启动MongoDB服务(位于 本地计算机 上)错误1067:进程意外终止。”
|
3月前
|
缓存 NoSQL Linux
在CentOS 7系统中彻底移除MongoDB数据库的步骤
以上步骤完成后,MongoDB应该会从您的CentOS 7系统中被彻底移除。在执行上述操作前,请确保已经备份好所有重要数据以防丢失。这些步骤操作需要一些基本的Linux系统管理知识,若您对某一步骤不是非常清楚,请先进行必要的学习或咨询专业人士。在执行系统级操作时,推荐在实施前创建系统快照或备份,以便在出现问题时能够恢复到原先的状态。
316 79
|
3月前
|
存储 NoSQL MongoDB
MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉
MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉
209 8
MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉
|
2月前
|
运维 NoSQL 容灾
告别运维噩梦:手把手教你将自建 MongoDB 平滑迁移至云数据库
程序员为何逃离自建MongoDB?扩容困难、运维复杂、高可用性差成痛点。阿里云MongoDB提供分钟级扩容、自动诊断与高可用保障,助力企业高效运维、降本增效,实现数据库“无感运维”。
|
6月前
|
NoSQL MongoDB 数据库
数据库数据恢复——MongoDB数据库服务无法启动的数据恢复案例
MongoDB数据库数据恢复环境: 一台Windows Server操作系统虚拟机上部署MongoDB数据库。 MongoDB数据库故障: 管理员在未关闭MongoDB服务的情况下拷贝数据库文件。将MongoDB数据库文件拷贝到其他分区后,对MongoDB数据库所在原分区进行了格式化操作。格式化完成后将数据库文件拷回原分区,并重新启动MongoDB服务。发现服务无法启动并报错。
|
7月前
|
存储 NoSQL MongoDB
微服务——MongoDB常用命令1——数据库操作
本节介绍了 MongoDB 中数据库的选择、创建与删除操作。使用 `use 数据库名称` 可选择或创建数据库,若数据库不存在则自动创建。通过 `show dbs` 或 `show databases` 查看所有可访问的数据库,用 `db` 命令查看当前数据库。注意,集合仅在插入数据后才会真正创建。数据库命名需遵循 UTF-8 格式,避免特殊字符,长度不超过 64 字节,且部分名称如 `admin`、`local` 和 `config` 为系统保留。删除数据库可通过 `db.dropDatabase()` 实现,主要用于移除已持久化的数据库。
493 0

推荐镜像

更多