MongoDB学习笔记07-MongoDB在Shell中执行更新

update()参数

update()函数接受以下四个参数:

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

强硬的文档替换式更新

此种更新操作类似于把之前的老文档删除,然后替换为更新的文档,也就是用新文档替换老文档,如下图:原文档中根本不存在age这个key,但是执行替换式更新后,不管老文档存在哪些key,更新最后都仅仅只会存在新的文档中的那些key(原文档的_id还会存在)。

> db.person.find()
{ "_id" : ObjectId("556c0b48361be67b8f01af2c"), "name" : "zhang" }
> db.person.find().pretty()  # 用格式化方式显示结果
{
    "_id" : ObjectId("556c0b48361be67b8f01af2c"),
    "name" : "zhang",
}
> db.person.update({name:"zhang"},{age:4})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find()
{ "_id" : ObjectId("556c0b48361be67b8f01af2c"), "age" : 4 }
>

这个时候如果是真的只需要更新name键的值,可以使用如下的方式:但是这种方式要注意一个问题,就是变量p必须通过findOne()去获得,如果通过find()方法获得,则后面的update方法会报错;而且因为findOne方法仅会返回查询文档匹配的一条集合文档,使用这种方式做update时,此处update满足更新条件的文档可能不止一条,那么更新就会失败,因为会出现集合中_id键值重复的现象。

> db.person.find()
{ "_id" : ObjectId("556c0b48361be67b8f01af2c"), "age" : 4 }
>
> var p = db.person.findOne()
> p.age = 14;
14
> db.person.update({"_id" : ObjectId("556c0b48361be67b8f01af2c")},p)
>
> db.person.find()
{ "_id" : ObjectId("556c0b48361be67b8f01af2c"), "age" : 14 }
>

不可以更新_id这个key的值,而不管更新后的_id值是否已经存在

使用修改器进行局部更新

$set修改器

{$set:{key:value}},如果满足更新条件的文档中存在$set修改器中的key时,则进行更新,否则进行添加

> db.person.find()
{ "_id" : 1001, "name" : "eee" }
{ "_id" : 1002, "name" : "eee" }
>
> db.person.update({name:"eee"},{$set:{name:"aaa",age:23}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "age" : 23 }
{ "_id" : 1002, "name" : "eee" }

  # 要修改多条相同的文档,则需要设置 multi 参数为 true
> db.person.update({name:"aaa"},{$set:{name:"aaa1",age:23}},{multi:true})

$inc修改器

{$inc:{key:value}},仅适用于数字类型,可以为指定的key对应的数字类型的值进行加减操作,如下:

> db.person.find()
{ "_id" : 1001, "name" : "aaa", "age" : 23 }
{ "_id" : 1002, "name" : "eee" }
>
> db.person.update({name:"aaa"},{$inc:{age:2}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "age" : 25 }
{ "_id" : 1002, "name" : "eee" }
>
> db.person.update({name:"aaa"},{$inc:{age:-2}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "age" : 23 }
{ "_id" : 1002, "name" : "eee" }
>

$unset修改器

{$unset:{key:value}},删除指定的key,如下:

> db.person.find()
{ "_id" : 1001, "name" : "aaa", "age" : 23 }
{ "_id" : 1002, "name" : "eee" }
>
> db.person.update({name:"aaa"},{$unset:{age:23}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa" }
{ "_id" : 1002, "name" : "eee" }
>

$push修改器

{$push:{key:value}},如果指定的key是数组,则往该数组中追加新的元素;如果指定的key不是数组,则中断操作;如果不存在指定的key,则创建,且类型为数组类型,并加入新的元素(可重复);如下:

> db.person.find()
{ "_id" : 1001, "name" : "aaa" }
{ "_id" : 1002, "name" : "eee" }
>
> db.person.update({name:"aaa"},{$push:{name:"java"}})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 16837,
                "errmsg" : "The field 'name' must be an array but is of type Str
ing in document {_id: 1001.0}"
        }
})
> db.person.update({name:"aaa"},{$push:{books:"java"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find()
{ "_id" : 1002, "name" : "eee" }
{ "_id" : 1001, "name" : "aaa", "books" : [ "java" ] }
> db.person.update({name:"aaa"},{$push:{books:"MongoDB"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find()
{ "_id" : 1002, "name" : "eee" }
{ "_id" : 1001, "name" : "aaa", "books" : [ "java", "MongoDB" ] }
>

$pushAll修改器

{$pushAll:{key:value}},与$push一样,只是它可以一次性批量加入一个数组中的所有元素,如下图:

> db.person.find()
{ "_id" : 1002, "name" : "eee" }
{ "_id" : 1001, "name" : "aaa", "books" : [ "java", "MongoDB" ] }
>
> db.person.update({name:"aaa"},{$pushAll:{books:["JavaEE","JSP"]}})
> db.person.find()
{ "_id" : 1002, "name" : "eee" }
{ "_id" : 1001, "name" : "aaa", "books" : [ "java", "MongoDB", "JavaEE", "JSP" ]
 }
>

$addToSet修改器

{$addToSet:{key:value}},与$push一样,只是当目标数组不存在该元素时才加入,如下图:

> db.person.find()
{ "_id" : 1002, "name" : "eee" }
> db.person.update({name:"eee"},{$addToSet:{name:"java"}})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 16837,
                "errmsg" : "Cannot apply $addToSet to a non-array field. Field n
amed 'name' has a non-array type String in the document _id: 1002.0"
        }
})
>  db.person.update({name:"eee"},{$addToSet:{books:"Java"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find()
{ "_id" : 1002, "name" : "eee", "books" : [ "Java" ] }
>
> db.person.update({name:"eee"},{$addToSet:{books:"Java"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
> db.person.find()
{ "_id" : 1002, "name" : "eee", "books" : [ "Java" ] }
>

$pop修改器

{$pop:{key:value}},从指定数组的头或尾删除一个元素,从头删除一个元素用小于 0 的值,从尾删除一个元素用大于 0 的值,如下图:

> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "java", "MongoDB", "JavaEE", "JSP","Spring" ] }
>
> db.person.update({_id:1001},{$pop:{books:-1}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "MongoDB", "JavaEE", "JSP", "Spring] }
>
> db.person.update({_id:1001},{$pop:{books:-2}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "JavaEE", "JSP", "Spring" ] }
>
> db.person.update({_id:1001},{$pop:{books:1}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "JavaEE", "JSP" ] }
>
> db.person.update({_id:1001},{$pop:{books:2}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "JavaEE" ] }
>

$pull修改器

{$pull:{key:value}},从指定数组中删除一个被指定的值,如下:

> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "JavaEE" ] }
> db.person.update({_id:1001},{$pull:{books:"JavaEE"}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ ] }
>

$pullAll修改器

{$pullAll:{key:value}},从指定数组中一次性删除多个被指定的值,如下:

> db.person.find()
{ "_id" : 1002, "name" : "eee", "books" : [ "Java", "JavaEE" ] }
>
> db.person.update({_id:1002},{$pullAll:{books:["JavaEE","Java"]}})
> db.person.find()
{ "_id" : 1002, "name" : "eee", "books" : [ ] }
>

数组定位器$

如果数组中有多个元素,需要对其中一部分进行更新,则可以使用定位器$。注意:当使用了books.price这种方式时,一定要加上引号,不然会报错。

> db.person.find()
{ "_id" : 1002, "books" : [ { "name" : "JSP", "price" : 23.5 },
            { "name" : "JAVA", "price" : 45.5 },
            { "name" : "Spring", "price" : 45.5 } ] }
>
> db.person.update({"books.price":45.5},{$set:{"books.$.author":"abc"}})
> db.person.find()
{ "_id" : 1002, "books" : [ { "name" : "JSP", "price" : 23.5 },
            { "name" : "JAVA", "price" : 45.5, "author" : "abc" },
            { "name" : "Spring", "price" : 45.5 } ] }
>

如果是知道数组元素索引,还可以通过索引的方式,比如把上面的books.$.author改为:books.0.author。这样更新的指定数组角标位置下的元素,即:

> db.person.update({"books.price":45.5},{$set:{"books.0.author":"abc"}})
> db.person.find()
{ "_id" : 1002, "books" : [ { "name" : "JSP", "price" : 23.5, "author" : "abc" },
            { "name" : "JAVA", "price" : 45.5 },
            { "name" : "Spring", "price" : 45.5 } ] }

$addToSet$each结合完成批量数组更新

如下:$each会循环后面的数组,把每个元素值进行$addToSet操作。

> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "Java" ] }
>
> db.person.update({_id:1001},{$addToSet:{books:{$each:["Java","JSP"]}}})
> db.person.find()
{ "_id" : 1001, "name" : "aaa", "books" : [ "Java", "JSP" ] }
>

$push$inc结合使用

比如要往文档的books这个key(数组)中加入一个元素,同时该文档的books_size这个key的大小加1,如下图:这个方式和修改器$addToSet没法配合使用,因为无法判断这个元素是否添加到了数组中

> db.person.find()
{ "_id" : 1002, "books" : [ "Java", "MongoDB" ], "books_size" : 2, "name" : "aaa" }
>
> db.person.update({_id:1002},{$push:{books: "JSP"}, $inc:{books_size:1}})
> db.person.find()
{ "_id" : 1002, "books" : [ "Java", "MongoDB", "JSP" ], "books_size" : 3, "name": "aaa" }
>

3.2版本新增方法

详情见官方文档
db.collection.updateOne()
db.collection.updateMany()
db.collection.replaceOne()

save() 方法

save() 方法通过传入的文档来替换已有文档。如果未传入_id值或_id值未找到则新增文档。

> db.person.save({"_id": 1002,name:"aaaaaa",age:24})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find().pretty()
{ "_id" : 1002, "name" : "aaaaaa", "age" : 24 }


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

文章标题:MongoDB学习笔记07-MongoDB在Shell中执行更新

文章字数:2.6k

本文作者:Bin

发布时间:2017-07-17, 17:21:38

最后更新:2019-08-06, 00:07:35

原始链接:http://coolview.github.io/2017/07/17/MongoDB/MongoDB%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B007-MongoDB%E5%9C%A8Shell%E4%B8%AD%E6%89%A7%E8%A1%8C%E6%9B%B4%E6%96%B0/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录