MongoDB 数组元素增删改

来源:互联网 发布:网络教育优点 编辑:程序博客网 时间:2024/06/06 22:45

与关系型数据库相比,MongoDB支持数组,将数组存储到文档之中。因此,与之对应的是数组的增删改查。对于有C语言基础的童鞋,数组应该不会陌生。数组的增删改查,在MongoDB中有相应的操作符来实现。本文主要描述数组的增删改相关操作符的使用。

有关数组的查询可以参考:MongoDB 数组查询

1、占位符$

占位符$的作用主要是用于返回数组中第一个匹配的数组元素值(子集),重点是第一个在更新时未显示指定数组中元素位置的情形下,占位符$用于识别元素的位置通过数组过滤条件找到的第一个匹配的元素值的文档将被更新使用示例        > db.students.insertMany([                { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] },                { "_id" : 2, "semester" : 1, "grades" : [ 90, 90, 92 ] },                { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] },                { "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] },                { "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] },                { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] }])          使用样式:                db.collection.find( { <array>: <value> ... },                                    { "<array>.$": 1 } )                db.collection.find( { <array.field>: <value> ...},                                    { "<array>.$": 1 } )        更新元素值样式:                                                    db.collection.update(                   { <array>: value ... },                   { <update operator>: { "<array>.$" : value } }                )                                           更新数组内嵌文档样式(使用.$.成员方式)                      db.collection.update(                   { <query selector> },                   { <update operator>: { "array.$.field" : value } }                )        更新操作时的占位符$匹配查询文档的第一个元素        数组字段必须为查询的过滤条件更新数组元素值        //下面查询semester值为1,grades为90的文档        //如下结果,所有包含90的文档都被返回                > db.students.find( { semester: 1, grades: { $eq: 90 } })//等价:db.students.find({semester:1,grades:90})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] }        { "_id" : 2, "semester" : 1, "grades" : [ 90, 90, 92 ] }        { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] }        //下面通过占位符$来过滤数组的结果,也即是只有第一个为90的值才会被显示,其余的元素值不被显示        > db.students.find( { semester: 1, grades: { $eq: 90 } },{ "grades.$": 1 } )        { "_id" : 1, "grades" : [ 90 ] }        { "_id" : 2, "grades" : [ 90 ] } //注意这里显示的是该文档的第一个90        { "_id" : 3, "grades" : [ 90 ] }        //下面使用占位符进行更新        > db.students.update({semester: 1, grades:90},{$set:{"grades.$":95}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  //提示1个文档被更新        //如下文档_id为1的数组值被更新为95        > db.students.find( { semester: 1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ] }        { "_id" : 2, "semester" : 1, "grades" : [ 90, 90, 92 ] }        { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] }        //下面使用multi:true选项,如下可知,2个匹配文档被更新        //但是仅仅是第一个元素值被更新(文档_id为2数值值为90的第二个元素未更新)        > db.students.update({semester: 1, grades:90},{$set:{"grades.$":95}},{multi:true})        WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })        > db.students.find( { semester: 1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ] }        { "_id" : 2, "semester" : 1, "grades" : [ 95, 90, 92 ] }        { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 95 ] }更新数组内嵌文档        //向集合增加一个文档        > db.students.insert(        ... {        ... _id:7,        ... grades: [        ...      { grade: 80, mean: 75, std: 8 },        ...      { grade: 85, mean: 90, std: 5 },        ...      { grade: 90, mean: 85, std: 3 }        ...   ]        ... })        WriteResult({ "nInserted" : 1 })        //如下所示,使用数组名.$.成员名的方式进行更新        //        > db.students.update(        ... { _id: 7, "grades.grade": 85 },        ... { $set: { "grades.$.std" : 6 } })        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"grades.grade":85},{ "grades.$": 1 })        { "_id" : 7, "grades" : [ { "grade" : 85, "mean" : 90, "std" : 6 } ] }更新数组内嵌文档(多条件匹配)        //对于多条件的匹配,使用$elemMatch        > db.students.update({"_id":7,grades:{$elemMatch:{grade:{$lte:90},mean:{$gt:80}}}},        ... { $set: { "grades.$.std" : 6 } })        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) //提示一条被更新        //验证结果,尽管有2个内嵌文档满足查询条件,但是只有第一个被更新        > db.students.find({"grades.std":6}).pretty()        {                "_id" : 7,      // Author: Leshami                "grades" : [    // Blog  : http://blog.csdn.net/leshami                        {                                "grade" : 80,                                "mean" : 75,                                "std" : 8                        },                        {                                "grade" : 85,                                "mean" : 90,                                "std" : 6                        },                        {                                "grade" : 90,                                "mean" : 85,                                "std" : 3                        }                ]        }

2、操作符$addToSet

当数组元素值不存在的时候,将该值添加到数组。否则,什么也不做。        样式:                             { $addToSet: { <field1>: <value1>, ... } }        $addToSet确保没有重复的项添加到数组集合,对于已经存在的重复元素不受影响。        $addToSet不能保证添加时元素的顺序        如果<field1>为空,操作失败,如果添加的值是数组,那么整个值将作为一个单个元素被追加        > db.students.update({"_id":6},{$addToSet:{grades:99}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"_id":6})        { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96, 99 ] }        //下面尝试再次添加99,如下提示有匹配,但是没有更新        > db.students.update({"_id":6},{$addToSet:{grades:99}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })               //下面的将grades:[100,101]作为一个整体元素添加到数组        > db.students.update({"_id":6},{$addToSet:{grades:[100,101]}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        //验证,100,101作为了一个整体,而非单个元素        > db.students.find({"_id":6})        { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96, 99, [ 100, 101 ] ] }              //结合$each操作符使用$addToSet        //$addToSet结合$each,允许$addToSet一次添加多个值到数组        //如下,我们需要将[96,99,100,101]这几个值添加到数组        >db.students.update({"_id":6},{$addToSet:{grades:{$each:[96,99,100,101]}}})        //如下面的查询结果,96,99元素值由于之前已经存在,因此未被添加,而100,101则被添加        > db.students.update({"_id":6},{$addToSet:{grades:{$each:[96,99,100,101]}}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"_id":6})        { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96, 99, [ 100, 101 ], 100, 101 ] }

3、操作符$push

$push添加一个指定的值到数组,如果是嵌套文档,使用.成员方式        样式:                { $push: { <field1>: <value1>, ... } }         行为:                如果被更新的文档该数组不存在,那么$push将添加数组字段和值                如果字段不是一个数组,操作失败                如果值是数组,那么整个数组作为一个单个元素添加到数组        $push的修改顺序(参考本小点后面的综合示例)                将添加的元素更新到数组                如果指定了排序,那么应用排序                如果指定了slice,那么切割数组                存储数组                        示例:        //字段不存在时的情形        > db.students.update({"_id":1},{$push:{score:80}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        //查看添加后的结果,score作为一个数组字段添加到文档        > db.students.find({"_id":1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 80 ] }        //再次对score字段进行$push        > db.students.update({"_id":1},{$push:{score:90}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        //查看添加后的结果,由于score数组字段存在,因此为其追加数组元素90        > db.students.find({"_id":1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 80, 90 ] }        > //$push结合$each,一次向数组push多个元素值,相同的元素值并没有忽略        > //这里是$push与$addToSet最大的一个差别,一个滤重,一个不滤重        > db.students.update({"_id":1},{$push:{score:{$each:[80,100,120]}}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"_id":1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 80, 90, 80, 100, 120 ] }        //$push结合$each,$slice,$sort的综合示例        //首先添加文档到集合        > db.students.insert({           "_id" : 8,           "quizzes" : [              { "wk": 1, "score" : 10 },              { "wk": 2, "score" : 8 },              { "wk": 3, "score" : 5 },              { "wk": 4, "score" : 6 }           ]        })        //使用如下更新操作        > db.students.update(           { _id: 8 },           {             $push: {               quizzes: {   //下面使用$each为数组添加3个元素                  $each: [ { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 } ],                  $sort: { score: -1 },  //基于socre倒叙排列                  $slice: 3              //仅保留3个元素               }             }           }        )        //更新后的结果如下,score,1088被保留,其余的被删除        > db.students.find({"_id":8}).pretty()        {                "_id" : 8,                "quizzes" : [                        {                                "wk" : 1,                                "score" : 10                        },                        {                                "wk" : 2,                                "score" : 8                        },                        {                                "wk" : 5,                                "score" : 8                        }                ]        }

4、操作符$pop

$pop操作符移除数组中的第一个或者最后一个元素(1为最后一个元素,-1为第一个元素)        如果是数组为嵌套文档,使用.成员方式        样式:                 { $pop: { <field>: <-1 | 1>, ... } }        //查看"_id"值为1的文档                     > db.students.find({"_id":1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 80, 90, 80, 100, 120, 80, 100, 120 ] }        //移除score最后一个元素        > db.students.update({"_id":1},{$pop:{score:1}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"_id":1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 80, 90, 80, 100, 120, 80, 100 ] }        //移除score第一个元素        > db.students.update({"_id":1},{$pop:{score:-1}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"_id":1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 90, 80, 100, 120, 80, 100 ] }        //移除嵌套数组的最后一个元素        > db.students.update({"_id":8},{$pop:{quizzes:1}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"_id":8})        { "_id" : 8, "quizzes" : [ { "wk" : 1, "score" : 10 }, { "wk" : 2, "score" : 8 } ] }

5、操作符$pull

$pull操作符从现有数组中移除与指定条件匹配的值或值的所有实例        样式:                { $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } }        说明:                如果指定的<condition>数组元素为内嵌文档时,$pull操作符应用<condition>,类似每个数组元素是集合中的文档一样                如果指定的<value>去移除数组,$pull仅仅移除满足指定条件的数组元素(精确匹配,包括顺序)                如果指定的<value>去移除一个文档,$pull仅仅移除字段和值精确匹配的数组元素素(顺序可以不同)        示例:        移除所有特定元素值                       > db.students.find({"_id":6})                { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96, 99, [ 100, 101 ], 100, 101 ] }                //移除单个数组元素值                > db.students.update({"_id":6},{$pull:{grades:99}})                WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })                //移除嵌套数组元素值                > db.students.update({"_id":6},{$pull:{grades:[100,101]}})                WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })                //验证结果                > db.students.find({"_id":6})                { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96, 100, 101 ] }                //下面使用$in来移除所有匹配元素                > db.students.update({"_id":6},{$pull:{grades:{$in:[95,96]}}})                WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })                //验证结果                > db.students.find({"_id":6})                { "_id" : 6, "semester" : 2, "grades" : [ 90, 100, 101 ] }          移除所有匹配的特定条件的数字元素                    //移除数组grades中大于等于100的元素                > db.students.update({"_id":6},{$pull:{grades:{$gte:100}}})                WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })                //如下查询100,101元素值已经不存在了                > db.students.find({"_id":6})                { "_id" : 6, "semester" : 2, "grades" : [ 90 ] }        移除文档型数组项目                > db.survey.insert([                {                   _id: 1,                   results: [                      { item: "A", score: 5 },                      { item: "B", score: 8, comment: "Strongly agree" }                   ]                },                {                   _id: 2,                   results: [                      { item: "C", score: 8, comment: "Strongly agree" },                      { item: "B", score: 4 }                   ]                }])                         //下面的update操作,移除results数组中嵌套文档score的值为8,item值为B的数值元素                > db.survey.update(                  { },                  { $pull: { results: { score: 8 , item: "B" } } },                  { multi: true }                )                WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 1 })   //2个匹配,1个更新                > db.survey.find().pretty()                { "_id" : 1, "results" : [ { "item" : "A", "score" : 5 } ] }                {                        "_id" : 2,                        "results" : [                                {                                        "item" : "C",                                        "score" : 8,                                        "comment" : "Strongly agree"                                },                                {                                        "item" : "B",                                        "score" : 4                                }                        ]                }

6、操作符$pullAll

该操作符从一个存在的数组中移除指定值得所有实例(即一次删除多个值)。        $pull操作符是移除一个指定查询的元素,$pullAll移除匹配列出值得所有元素        样式:                { $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } }        说明:                当指定的<field>是一个内嵌文档或数组时,使用.成员方式                如果<value>是一个文档或者数组,$pullAll仅仅精确移除匹配指定<value>数组的元素(顺序要求匹配)        示例        > db.students.find({"_id":{$in:[1,5]}})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 90, 80, 100, 120, 80, 100 ] }        > db.students.find({"_id":1})        { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 95 ], "score" : [ 90, 80, 80 ] }        > db.students.find({"_id":5}).pretty()        {                "_id" : 5,                "semester" : 2,                "grades" : [                        88,                        88,                        92                ],                "quizzes" : [                        {                                "wk" : 5,                                "score" : 8                        },                        {                                "wk" : 6,                                "score" : 7                        },                        {                                "wk" : 7,                                "score" : 6                        }                ]        }        > db.students.update({"_id":5},{$pullAll:{"quizzes":[{"wk" : 5,"score" : 8}]}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.update({"_id":5},{$pullAll:{"quizzes":[{"wk" : 7,"score" : 6}]}})        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })        > db.students.find({"_id":5}).pretty()        {                "_id" : 5,                "semester" : 2,                "grades" : [                        88,                        88,                        92                ],                "quizzes" : [                        {                                "wk" : 6,                                "score" : 7                        }                ]        }

DBA牛鹏社(SQL/NOSQL/LINUX)

0 0
原创粉丝点击