• mongodb的修改器


           在mongodb中通常文档只会有一部分要更新,利用原子的更新修改器,可以做到只更新文档的一部分键值,而且更新极为高效,更新修改器是种特殊的键,用来指定复杂的更新操作,比如调整、增加、或者删除键,还可以操作数组和内嵌文档。增加、修改或删除键的时候,应该使用$修改器。要把"foo"的值设备"bar",常见的错误做法如下:

    db.coll.update(criteria,{"foo":"bar"})

    这种情况是不对的,实际上这种做法会把整个文档用{"foo":"bar"}替换掉,一定要使用以$开头的修改器来修改键/值对。

    1. $set修改器

    $set  修改器用来指定一个键值。如果这个键不存在,则创建他,他对更新模式或者用户定义键来说非常方便。

    > db.users.findOne()
    {
            "_id" : ObjectId("56fe7df8b322e3ff1dabf834"),
            "name" : "joe",
            "age" : 30,
            "sex" : "male",
            "location" : "Wisconsin",
            "favorite book" : "war and pace"
    }
    
    > db.users.update({"name":"joe"},{"$set":{"favorite book":["cat's cardle","foundation trilogy","ender's game"]}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("56fe7df8b322e3ff1dabf834"),
            "name" : "joe",
            "age" : 30,
            "sex" : "male",
            "location" : "Wisconsin",
            "favorite book" : [
                    "cat's cardle",
                    "foundation trilogy",
                    "ender's game"
            ]
    }

    2. $set用来修改内嵌文档

    > db.blog.insert({"title":"a blog post","author":{"name":"joe","email":"joe@example.com"}})
    WriteResult({ "nInserted" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "author" : {
                    "name" : "joe",
                    "email" : "joe@example.com"
            }
    }
    > db.blog.update({"author.name":"joe"},{"$set":{"author.name":"joe schmoe"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "author" : {
                    "name" : "joe schmoe",
                    "email" : "joe@example.com"
            }
    }
    > db.blog.update({"title":"a blog post"},{"$set":{"author.name":"joe schmoe op"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "author" : {
                    "name" : "joe schmoe op",
                    "email" : "joe@example.com"
            }
    }
    >

    3. $unset修改器

    $unset修改用于将键删除

    > db.users.findOne()
    {
            "_id" : ObjectId("56fe7df8b322e3ff1dabf834"),
            "name" : "joe",
            "age" : 30,
            "sex" : "male",
            "location" : "Wisconsin",
            "favorite book" : [
                    "cat's cardle",
                    "foundation trilogy",
                    "ender's game"
            ]
    }
    > db.users.update({"name":"joe"},{"$unset":{"favorite book":1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("56fe7df8b322e3ff1dabf834"),
            "name" : "joe",
            "age" : 30,
            "sex" : "male",
            "location" : "Wisconsin"
    }

    4. $inc修改器

    $inc其用来增加或减少已有的键的键值,或者在键不存在的时候创建一个键。

    > db.games.insert({"game":"pinball","user":"joe"})
    WriteResult({ "nInserted" : 1 })
    > db.games.findOne()
    {
            "_id" : ObjectId("5770a1394f533aa7535d46d4"),
            "game" : "pinball",
            "user" : "joe"
    }
    > db.games.update({"game":"pinball","user":"joe"},{"$inc":{"score":50}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.games.findOne()
    {
            "_id" : ObjectId("5770a1394f533aa7535d46d4"),
            "game" : "pinball",
            "user" : "joe",
            "score" : 50
    }


    为"score"键增加50再减少20

    > db.games.update({"game":"pinball","user":"joe"},{"$inc":{"score":50}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.games.findOne()
    {
            "_id" : ObjectId("5770a1394f533aa7535d46d4"),
            "game" : "pinball",
            "user" : "joe",
            "score" : 100
    }
    > db.games.update({"game":"pinball","user":"joe"},{"$inc":{"score":-20}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.games.findOne()
    {
            "_id" : ObjectId("5770a1394f533aa7535d46d4"),
            "game" : "pinball",
            "user" : "joe",
            "score" : 80
    }

            以上"$inc"与"$set"的用法类似,就是专门用来增加或减少数字的。"$inc"只能用于整数、长整数或双精度浮点数,要是在其他类型的数据上就会导致操作失败,其中包括很多语言会自动转换成数字的类型,例如null,布尔类型,或数字构成的字符串。"$inc"键的值必须为数字,不能使用字符串、数组和其他非数字的值,否则会报错,要修改其他类型,只能使用"$set"。

    如下:

    > db.foo.insert({"count":"1"})
    WriteResult({ "nInserted" : 1 })
    > db.foo.find()
    { "_id" : ObjectId("5770befc4f533aa7535d46d5"), "count" : "1" }
    > db.foo.update({},{"$inc":{"count":1}})
    WriteResult({
            "nMatched" : 0,
            "nUpserted" : 0,
            "nModified" : 0,
            "writeError" : {
                    "code" : 16837,
                    "errmsg" : "Cannot apply $inc to a value of non-numeric type. {_id: ObjectId('5770befc4f533aa7535d46d5')} has the field 'count' of non-numeric type String"
            }
    })
    
    > db.foo.update({},{$set:{count:2}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.foo.find()
    { "_id" : ObjectId("5770befc4f533aa7535d46d5"), "count" : 2 }
    >

    5. 数组修改器 $push

    数组修改器,顾名思义它只可以用于操作数组,只能用在值为数组的键上。$push修改器如果指定的值已经存在,"$push"会想已有的数组末尾加入一个元素,要是没有就会创建一个新的数组。

    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "author" : {
                    "name" : "joe schmoe op",
                    "email" : "joe@example.com"
            }
    }
    > db.blog.update({"title":"a blog post"},{"$unset":{"author":1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    { "_id" : ObjectId("57709da84f533aa7535d46d3"), "title" : "a blog post" }
    > db.blog.update({"title":"a blog post"},{"$push":{"comments":{"name":"joe","email":"joe@example.com","content":"nice post"}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "comments" : [
                    {
                            "name" : "joe",
                            "email" : "joe@example.com",
                            "content" : "nice post"
                    }
            ]
    }

    为blog集合"a blog post"文档再增加一条评论:

    > db.blog.update({"title":"a blog post"},{"$push":{"comments":{"name":"bob","email":"bob@example.com","content":"good post"}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "comments" : [
                    {
                            "name" : "joe",
                            "email" : "joe@example.com",
                            "content" : "nice post"
                    },
                    {
                            "name" : "bob",
                            "email" : "bob@example.com",
                            "content" : "good post"
                    }
            ]
    }

    6. 数组修改器 $ne

    $ne也是用来操作数组的修改器,在查询文档中,如果一个值不在数组里面就把他加进去,如果在不添加。

    > db.users.insert({"name":"joe","emails":["joe@example.com","joe@gmail.com","joe@yahoo.com"]})
    WriteResult({ "nInserted" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com"
            ]
    }
    > db.users.update({"name":"joe","emails":{$ne:"joe@gmail.com"}},{$push:{"emails":"joe@gmail.com"}})
    WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })                                    --nMatched为0表示没有修改
    > db.users.update({"name":"joe","emails":{$ne:"joe@itpub.com"}},{$push:{"emails":"joe@itpub.com"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com"
            ]
    }

    以上这种方式也可以使用$addToSet实现。

    7. 数组修改器 $addToSet

    $addToSet也是用来操作数组的修改器,实现的功能与$ne修改器相同,且更为方便。使用$addToSet修改器可以避免重复。

    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com"
            ]
    }
    > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{"emails":"joe@gmail.com"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })     --原文档里已有"joe@gmail.com",修改完也没有产生重复值
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com"
            ]
    }
    > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{"emails":"joe@163.com"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com"
            ]
    }

    8. 数组修改器 $each

    $each数组修改器要和$addToSet修改结合起来用,可以一次添加多个不同的值。例如上面的例子中,我们一次添加多个email值, 如下:

    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com"
            ]
    }
    > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{$each:["joe@example.com","joe@python.com","joe@php.com"]}})
    WriteResult({
            "nMatched" : 0,
            "nUpserted" : 0,
            "nModified" : 0,
            "writeError" : {
                    "code" : 52,
                    "errmsg" : "The dollar ($) prefixed field '$each' in '$each' is not valid for storage."
            }
    })
    > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{"emails":{$each:["joe@example.com","joe@python.com","joe@php.com"]}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com",
                    "joe@python.com",
                    "joe@php.com"
            ]
    }
    >

    9. 数组修改器 $pop

    $pop修改器主要于从数组中删除元素,他可以从数组中的任何一端删除元素,
    例如:
    {$pop:{key:1}} 从数组末尾删除一个元素
    {$pop:{key:-1}} 从数组头部删除一个元素

    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com",
                    "joe@python.com",
                    "joe@php.com"
            ]
    }
    > db.users.update({"name":"joe"},{$pop:{"emails":1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@example.com",
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com",
                    "joe@python.com"
            ]
    }
    > db.users.update({"name":"joe"},{$pop:{"emails":-1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com",
                    "joe@python.com"
            ]
    }

    有时我们需要基于特定条件来删除元素,而不仅仅依据位置,就可以使用$pull修改器

    10. 数组修改器 $pull

    $pull修改器和$pop修改类似,都是用来删除数组中的元素
    $pull可以基于特定条件来删除元素
    $pull会将所有匹配到的数据全部删掉,如对数组[1,2,1,1]执行pull 1,得到的结果就是只有一个元素的数组[2]

    例如我们想删除emails数组中的"joe@163.com"和"joe@itpub.com"两个元素:

    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com",
                    "joe@python.com"
            ]
    }
    > db.users.update({"name":"joe"},{$pull:{"emails":["joe@163.com","joe@itpub.com"]}})   
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })  --好像不能一次删除多个,没有起作用
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@itpub.com",
                    "joe@163.com",
                    "joe@python.com"
            ]
    }
    > db.users.update({"name":"joe"},{$pull:{"emails":"joe@163.com"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.update({"name":"joe"},{$pull:{"emails":"joe@itpub.com"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("5770ca42e90c1adc80040a08"),
            "name" : "joe",
            "emails" : [
                    "joe@gmail.com",
                    "joe@yahoo.com",
                    "joe@python.com"
            ]
    }

    11. 数组的定位修改器 $

    若是数组有多个值,而我们只想对其中一部分进行操作,有两种方法可以实现这种操作。
    两种方法操作数组中的值:通过位置或定位操作符("$")

    数组都是以0开头的,可以将下标直接作为键来选择元素。

    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "comments" : [
                    {
                            "name" : "joe",
                            "email" : "joe@example.com",
                            "content" : "nice post"
                    },
                    {
                            "name" : "bob",
                            "email" : "bob@example.com",
                            "content" : "good post"
                    }
            ]
    }
    > db.blog.update({"title":"a blog post"},{$set:{"comments.1.name":"livan"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "comments" : [
                    {
                            "name" : "joe",
                            "email" : "joe@example.com",
                            "content" : "nice post"
                    },
                    {
                            "name" : "livan",
                            "email" : "bob@example.com",
                            "content" : "good post"
                    }
            ]
    }
    > db.blog.update({"title":"a blog post"},{$set:{"comments.1.email":"livan@example.com"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "comments" : [
                    {
                            "name" : "joe",
                            "email" : "joe@example.com",
                            "content" : "nice post"
                    },
                    {
                            "name" : "livan",
                            "email" : "livan@example.com",
                            "content" : "good post"
                    }
            ]
    }

    在很多情况下,不预先查询文档就不能知道要修改数组的下标,为了克服这种困难,mongodb提供了定位操作符"$",
    用来定位查询文档已经匹配的元素,并进行更新,定位符只更新第一个匹配的元素。
    例如:用户john把名字改成了jim,就可以用定位符来替换评论中的名字:
    db.blog.update({"comments.author":"john"},{$set:{"comments.$.author:"john"}})
    可以理解为{"comments.author":"john"}查询条件定位到第一个元素,就执行{$set:{"comments.$.author:"john"}},"$"定位符就表示找到的第一个元素

    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "comments" : [
                    {
                            "name" : "joe",
                            "email" : "joe@example.com",
                            "content" : "nice post"
                    },
                    {
                            "name" : "livan",
                            "email" : "livan@example.com",
                            "content" : "good post"
                    }
            ]
    }
    > db.blog.update({"comments.name":"livan"},{$set:{"comments.$.email":"bob@example.com"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.update({"comments.name":"livan"},{$set:{"comments.$.name":"bob"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.blog.findOne()
    {
            "_id" : ObjectId("57709da84f533aa7535d46d3"),
            "title" : "a blog post",
            "comments" : [
                    {
                            "name" : "joe",
                            "email" : "joe@example.com",
                            "content" : "nice post"
                    },
                    {
                            "name" : "bob",
                            "email" : "bob@example.com",
                            "content" : "good post"
                    }
            ]
    }

                                                                                         

                                                                 《MongoDB权威指南中文版》

                                                               mongdb数组修改     http://blog.163.com/wm_at163/blog/static/1321734902012526111917601/

  • 相关阅读:
    从JavaScript的事件循环到Promise
    Vuex初识
    npm常用命令及版本号浅析
    npm install 时--save-dev和--save的区别
    Json-Server模拟数据接口开发
    基于Express+Socket.io+MongoDB的即时聊天系统的设计与实现
    fileInput实战总结
    找工作总结
    nodejs-基本语法
    初识nodejs
  • 原文地址:https://www.cnblogs.com/myrunning/p/5655615.html
Copyright © 2020-2023  润新知