MongoDB更新文档
转载请出自出处:http://eksliang.iteye.com/blog/2174104
MongoDB对文档的CURD,前面的博客简单介绍了,但是对文档更新篇幅比较大,所以这里单独拿出来。
语法结构如下:
db.collection.update( criteria, objNew, upsert, multi)
参数含义
参数 |
含义 |
criteria |
update的查询条件,类似sql update查询内where后面的 |
objNew |
update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的修改列 |
upsert |
这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。 |
multi |
mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。 |
一、文档替换
1、最简单的更新就是用一个新文档完全替换匹配文档。
参考实例
> user=db.user.findOne()
{
"_id" : ObjectId("54ae6fb5b94cf1b60f10570f"),
"name" : "ickes",
"pwd" : "xl1",
"sal" : 1
}
> user.sal=1200 --将该文档的sal改为1200
1200
> db.user.update({"pwd":"xl1"},user) --完全用新的文档替换集合中pwd=xl的文档
> db.user.findOne() --在次查看,替换成功
{
"_id" : ObjectId("54ae6fb5b94cf1b60f10570f"),
"name" : "ickes",
"pwd" : "xl1",
"sal" : 1200
}
温馨提示:当查询条件匹配了多个文档,然后更新时由于第二个参数的存在就产生的重复“_id”的值。数据库就会抛出错误。
二、使用更新修改器
通常文档只会有一部分需要更新。可以使用“更新修改器”指定对文档中的某些字段进行更新。更新修改器是特殊的键,用来指定复杂的更新操作,比如修改、添加、删除键,还可以操作数组和内嵌文档。
1)$inc修改器
这个修改器是用来计数增加的(如果键不存在会在文档中增加键),例如有一个网站,当有人访问页面时,就计数加一,来做统计
参考实例
> db.iteye.findOne()
{
"_id" : ObjectId("54af318953b409e1c2efa8d8"),
"title" : "iteye",
"count" : 1 --该值本来为1
}
> db.iteye.update({"title":"iteye"},{"$inc":{"count":1}}) --计数修改加1,如果是2,就会加2
> db.iteye.find() --再次查看
{ "_id" : ObjectId("54af318953b409e1c2efa8d8"), "title" : "iteye", "count" : 2 } --修改成功
2)$set、$unset修改器
“$set”修改器用来指定一个字段的值。如果这个字段不存在,则创建他。$unset就是将文档中的某个键完全删除
参考实例
> db.user.find()
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xialiang" }
> db.user.update({"name":"xialiang"},{"$set":{"name":"xl","title":"MongoDB"}})
--用set修改器修改第一条数据,name本来就存在,那么修改,而title在原文档中本来不存在,自动添加
> db.user.find() --查看修改结果,发现跟理论一样
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "title" : "MongoD
B" }
“$set”修改器修改嵌套文档
参考实例
> db.iteye.find() --查看iteye集合,里面有一个blog的内嵌文档
{ "_id" : ObjectId("54af318953b409e1c2efa8d8"), "title" : "iteye", "count" : 4,
"blog" : { "title" : "eksliang.iteye.com", "name" : "ickes" } }
> db.iteye.update({"blog.name":"ickes"},{"$set":{"blog.name":"xl"}}) --用$set修改内嵌文档
> db.iteye.find() --查看当前修改,很明显修改成功
{ "_id" : ObjectId("54af318953b409e1c2efa8d8"), "title" : "iteye", "count" : 4,
"blog" : { "title" : "eksliang.iteye.com", "name" : "xl" } }
“$unset”删除文档的键
参考实例
> db.user.find({"name":"xl"}) --查询name=xl的文档
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "title" : "MongoD
B" }
> db.user.update({"name":"xl"},{"$unset":{"title":1}}) --删除title这个键(这里删除键的值,官网说为任意数字,我测试时,任何值都是没有任何问题的)
> db.user.find({"name":"xl"}) --再次查看,发现键删除成功
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl" }
三、数组修改器
1)、"$push"修改器
如果数组已经存在,“$push”会向已有的数组末尾加入一个元素,要是没有就创建一个新的数组。
参考实例
> db.user.find({"name":"xl"})--先查看name=xl的文档
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1 }
> db.user.update({"name":"xl"},{"$push":{"arrys":"aa"}}) --向arrays数组末尾添加一个元素
> db.user.update({"name":"xl"},{"$push":{"arrys":"bb"}}) --在添加一个
> db.user.find({"name":"xl"})--再次查看,果真加进去了,而且arrays这个键本来是不存在,现在有了
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1, "arr
ys" : [ "aa", "bb" ] }
2)、$each子操作符
单独使用“$push”修改器,每次执行update,都只能加一个元素,怎么添加一次向数组中添加多个元素,使用子操作符$each就可以轻松搞定
> db.user.find({"name":"xl"})
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1, "arr
ys" : [ "aa", "bb" ] } --更新之前,数组中只有两个元素
> db.user.update({"name":"xl"},{"$push":{"arrys":{"$each":["cc","dd","ee"]}}})
--使用$eash子操作符,一次向数组后面添加三个元素
> db.user.find({"name":"xl"}) --再次查看,果真不负众望
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1, "arr
ys" : [ "aa", "bb", "cc", "dd", "ee" ] }
3)$slice设定数组的最大长度
如果希望数组的最大长度是固定的,那么可以将“$slice”和“$push”组合在一起使用,这样就可以保证数组不会超出设定的最大长度,这实际上就得到了一个最多包涵N个元素的数组
参考实例
> db.user.find({"name":"xl"})
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1, "arr
ys" : [ "aa", "bb", "cc", "dd", "ee" ] } --数组中本来就有5个元素
> db.user.update({"name":"xl"},
... {"$push":{"arrys":{
... "$each":["ff","gg","hh"],--在添加3个
... "$slice":-6}}}) --限制数组的最大长度为6,该值不能为正,取其绝对值
> db.user.find({"name":"xl"})
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1, "arr
ys" : [ "cc", "dd", "ee", "ff", "gg", "hh" ] } --本来应该是8个的,现在只有6个
其实上面这个例子会限制数组只包涵最后加了的6个元素,也就是说,把新元素加入数组后,最后的6个元素会得以保留,需要注意的是$slice必须为负数。
4、$sort,添加元素后,对数组进行排序
参考实例
> db.user.find({"name":"xl"})
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1, "arr
ys" : [ "cc", "dd", "ee", "ff", "gg", "hh" ] } --本来是c~h
> db.user.update({"name":"xl"},
... {"$push":{"arrys":{
... "$each":["zz","xx","aa"], --无序的添加三个
... "$slice":-6, --数组中最多存放6个元素
... "$sort":-1}}}) --小于0降序,大于0升序
> db.user.find({"name":"xl"}) --查看结果,果然是最后六个元素的降序
{ "_id" : ObjectId("54ae6fb5b94cf1b60f105710"), "name" : "xl", "count" : 1, "arr
ys" : [ "gg", "ff", "ee", "dd", "cc", "aa" ] }
温馨提示:必须要注意的是不能将$slice或者$sort与$push配合使用,$slice与$sort的使用必须带上$each
四、将数组作为数据集使用(MongoDB的数组是允许出现重复元素的)
有时候我们想把数组当做数据集使用,从而保证数组内的元素不能重复。例如我的用户文档中emails用来保存用户的邮箱地址,只有当添加进来的邮箱地址不存在,才添加进来。
$addToSet修改器就是做这件事情的
参考实例
> db.user.find({"name":"cjc"})
{ "_id" : ObjectId("54af71b253b409e1c2efa8da"), "name" : "cjc", "emails" : [ "cj
c@163.com" ] } --emails数组中目前只有一个元素
> db.user.update({"name":"cjc"}, --添加一个eksliang@163.com的邮件地址
... {"$addToSet":{
... "emails":"eksliang@163.com"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.update({"name":"cjc"}, {"$addToSet":{ "emails":"eksliang@163.com"}}) --再添加一次
> db.user.find({"name":"cjc"}) --再次查看发现,其实只添加了一个
{ "_id" : ObjectId("54af71b253b409e1c2efa8da"), "name" : "cjc", "emails" : [ "cj
c@163.com", "eksliang@163.com" ] }
添加新的邮件地址时,使用$addToSet修改器,可以避免插入重复地址
参考实例二:将$addToSet和$each组合起来,可以添加多个不同的值
> db.user.find({"name":"cjc"})
{ "_id" : ObjectId("54af71b253b409e1c2efa8da"), "name" : "cjc", "emails" : [ "cj
c@163.com", "eksliang@163.com" ] } --原本该数组里面有两个元素
> db.user.update({"name":"cjc"},
... {"$addToSet":{
... "emails":{
... "$each":["eksliang@163.com","ickes@163.com"]} --使用$each批量添加两个
... }})
> db.user.find({"name":"cjc"})--再次查看,发现重复邮件地址eksliang@163.com没有添加进来
{ "_id" : ObjectId("54af71b253b409e1c2efa8da"), "name" : "cjc", "emails" : [ "cj
c@163.com", "eksliang@163.com", "ickes@163.com" ] }
5.从文档的数组中删除元素($pop或者$pull)
有几个从数组中删除元素的方法。若是把数组看出队列或者栈,可以使用“$pop”,这个修改器可以从数组的任何一端删除元素。{"$pop":{"key":1}}从数组末尾删除一个元素,{"$pop":{"key":-1}}则从头部删除。
参考实例一:
> db.user.find() --查看当前集list数组里面有四个元素;
{ "_id" : ObjectId("54af77a953b409e1c2efa8db"), "list" : [ "aa", "bb", "cc", "dd
" ] }
> db.user.update({},{"$pop":{"list":-1}}) --小于0,从前面删除一个元素;
> db.user.find() --查看,发现删除“aa”元素删除了;
{ "_id" : ObjectId("54af77a953b409e1c2efa8db"), "list" : [ "bb", "cc", "dd" ] }
> db.user.update({},{"$pop":{"list":1}}) --大于0,从后面删除一个元素;
> db.user.find() --查看,发现“dd”元素删除了;
{ "_id" : ObjectId("54af77a953b409e1c2efa8db"), "list" : [ "bb", "cc" ] }
有时需要基于特定条件删除元素,而不仅仅是依据元素位置,这时可以使用"$pull"
参考实例二:
> db.user.find() --查看当前数组中有4个元素,两个元素相同;
{ "_id" : ObjectId("54af7a6d53b409e1c2efa8de"), "list" : [ "aa", "bb", "bb", "dd
" ] }
> db.user.update({},{"$pull":{"list":"bb"}}) --删除list数组中等于"bb"的元素;
> db.user.find() --再次查看,删除成功!
{ "_id" : ObjectId("54af7a6d53b409e1c2efa8de"), "list" : [ "aa", "dd" ] }
从上面实例可以看出"$pull"修改器可以将数组中所有匹配的元素删除
六、save()函数
save()函数,如果文档不存在,他会自动创建文档,如果文档不存在他会创建新的文档
看下这个函数的源码如下:
function ( obj , opts ){
if ( obj == null )
throw "can't save a null";
if ( typeof( obj ) == "number" || typeof( obj) == "string" )
throw "can't save a number or string"
if ( typeof( obj._id ) == "undefined" ){
obj._id = new ObjectId();
return this.insert( obj , opts );
}
else {
return this.update( { _id : obj._id } , obj , Object.merge({ upsert:true
}, opts));
}
}
可以看到他的逻辑相当简单,如果添加的文档含有"_id",那么他是调用update(obj,obj,true)方法,如果添加的文档不含有"_id"那么直接调用insert()完成添加。
分享到:
相关推荐
MongoDB是一种流行的开源、分布式文档型数据库,以其灵活性、高性能和易用性而备受开发者青睐。作为NoSQL数据库的一种,它存储数据的方式不同于传统的表结构,而是采用键值对、文档、集合的形式。MongoDB的官方中文...
2.了解NoSQL和文档数据库 3.要求 4.其他帮助资源 4.1。支持 4.1.1。社区论坛 4.1.2。专业支持 4.2。发展之后 5.新&值得注意的 5.1。Spring Data MongoDB 2.1中的新特性 5.2。Spring Data MongoDB 2.0中的新特性 5.3...
### Spring Data MongoDB中文文档知识点概览 #### 一、Spring Data MongoDB概述 - **Spring Data MongoDB** 是 **Spring Data** 家族的一员,它提供了一种简单的方式来与 MongoDB 数据库进行交互。通过 Spring Data...
- **数据映射和类型转换**:如何处理对象与MongoDB文档之间的映射和转换。 - **映射配置**:提供了配置映射规则的方法。 #### 15. 跨存储支持 - **跨商店配置**:支持跨多个MongoDB实例的数据操作。 - **编写跨商店...
Spring Data MongoDB API。 Spring Data MongoDB 开发文档。
这个驱动程序提供了一组API,使得开发人员能够轻松地连接到MongoDB服务器、创建数据库、集合,并执行CRUD(创建、读取、更新、删除)操作。例如,使用`MongoClient`类可以建立到MongoDB服务器的连接,`MongoDatabase...
这是一个用于MongoDB操作的类,它封装了对MongoDB的基本CRUD(创建、读取、更新、删除)操作,并且提供了一个更加面向对象的接口,使得开发者可以通过更加自然的方式来操作MongoDB。 SpringData MongoDB支持查询...
MongoDB是一个高性能、开源、无模式的分布式文档型数据库,它以其灵活性和可扩展性受到青睐。而PHP作为服务器端脚本语言,因其易学易用性而广受欢迎,因此将PHP与MongoDB结合,可以构建高效的数据驱动应用。 本文档...
mongodb分片配置.docx Mongodb.chm mongodb安装以及基本操作.docx MongoDB使用手册.doc mongo分布式研究.docx 有这5个文档足够学习Mongodb使用了
5. 更新操作可以替换整个文档或指定字段。 6. 内置 MapReduce 功能,用于数据批量处理和聚合操作,Map 函数遍历记录,Reduce 函数处理结果。 7. GridFS 用于存储大量小文件。 8. 支持在服务器端执行 JavaScript 脚本...
### MongoDB 3.2.4 说明文档知识点总结 #### 一、MongoDB简介 **1.1 文档型数据库** MongoDB 是一种基于分布式文件存储的开源文档型数据库系统,设计初衷是为了解决传统关系型数据库在处理大规模非结构化数据时...
对于数据库的安全性,MongoDB文档将介绍安全机制的原理和概念,并提供安全性教程来指导用户如何配置认证、授权以及加密等安全选项。安全性参考部分则详细列举了相关的安全命令和设置,是实际操作时的重要参考。 ...
MongoDB 是一个流行的开源文档型数据库系统,以其灵活性、高性能和可扩展性而备受开发者喜爱。这份"mongodb 学习文档"涵盖了多个方面的内容,包括MongoDB的基础概念、安装配置、数据模型、查询操作、聚合框架、索引...
MongoDB 3.6 中文文档
1. 使用sudo apt-get update更新软件源,然后sudo apt-get install mongodb-server安装MongoDB。 2. 配置MongoDB服务,编辑/etc/mongod.conf文件,根据需求调整存储路径、端口等设置。 3. 启动MongoDB服务,使用命令...
3. **CRUD操作**:MongoDB提供了创建(Create)、读取(Read)、更新(Update)和删除(Delete)数据的基本操作。与SQL相比,它们具有不同的语法和方法,例如使用`insertOne()`、`find()`、`updateOne()`和`delete...
“MongoDBClientTest”可能是一个示例项目,展示了如何在实际应用中使用编译好的驱动程序,包括连接到MongoDB服务器,执行查询,插入和更新文档等操作。这有助于开发者了解如何在自己的项目中集成MongoDB C++驱动。 ...
MongoTemplate 是Spring Data MongoDB 提供的核心类,用于执行CRUD(创建、读取、更新、删除)操作。它提供了丰富的API,可以执行复杂查询和操作。 5. **Repository 接口** Spring Data MongoDB 提供了Repository...
**mongoDB说明文档知识点解析** MongoDB是一种非关系型数据库,属于NoSQL家族的一员,以其高性能、高可用性以及灵活性而著称。本说明文档旨在深入解析MongoDB的关键概念、使用规则及其在不同领域的应用实践。 ### ...