mongo更新操作

一 基本概念及注意事项

    1 MongoDB中数据的结构为:库、集合、文档,类似于关系型数据库中的库、表、行,只是mongo集合与集合之间不能像关系型数据库表与表之间可以关联查询,mongo的集合对文档没有限制

    2 mongo更新操作是针对文档进行操作,即你进行的操作都要有转化为文档的意识

    3 mongo更新需要两个文档,第一个文档为匹配条件文档,也就是查询匹配文档,第二个文档为更新内容文档。如果需要更新所有文档,可将条件文档写为"{}"

    4 mongo的shell由javascript编写,js中只有一种数字类型,但MongoDB中有3种数字类型(32位整数、64位整数、64位浮点数),默认情况下,shell中的数字都被MongoDB当作是双精度数,这意味着如果你从数据库中获得的是一个32位整数,修改文档后,将文档存回数据库的时候,这个整数也被换成了浮点数,即便保持这个整数原封不动也会这样。所以尽量不要在shell下覆盖整个文档。


二 更新语法

更新语法有update和findAndModify等方式,下面依次介绍

1 update方式

db.collection.update( criteria, objNew,upsert, multi)

    criteria : update的查询条件,类似关系型数据库update查询条件的where。

    objNew: update的对象和一些更新的操作符(如$,$inc...)等,类似关系型数据库update中的set。

    upsert :如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。

    multi:默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来的多条记录全部更新。

2 findAndModify方式

findAndModify更新方法:

db.collection.findAndModify({

    query:{},查询限定文档

    update:{},更新文档,不能与remove同时出现

    remove:true|false,删除符合查询条件的文档,不能与update同时出现

    new:true|false,true:返回更新后的文档,false:返回更新前的文档,默认false

    sort:{},排序条件,与sort函数的参数一致

    fields:{},投影操作,与find的第二个参数一致

    upset:true|false如果不存在update的记录,是否插入,true:插入,false:不插入

})

示例:

db.inventory.find({amount:{$gt:50}})

{ "_id" :ObjectId("559f9f085adecff7fdd402b4"), "name" :"t4", "amount" : 60, "havemoney" :true,"tags" : [ "book" ] }

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : ["book","car", "dddc", "dddc" ] }

db.inventory.findAndModify({

    query:{amount:{$gt:50}},

    update:{$push:{tags:"dddc"}},

    sort:{amount:-1},

    new:true,

    upsert:true

})

db.inventory.find({amount:{$gt:58}})

{ "_id" :ObjectId("559f9f085adecff7fdd402b4"), "name" :"t4", "amount" : 60, "havemoney" : true,"tags" : [ "book" ] }

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ "book","car", "dddc", "dddc", "xia" ] }

findAndModify只会更新一条文档。sort不是对更新完成后返回的结果进行排序,而是对查询结果进行排序,更新排序后的第一条文档

三 更新操作符

1、$inc用法:{$inc : {field:value }},意思是对一个数字key进行加法运算(value可以为负数)

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 62, "havemoney" : true }

db.inventory.update({amount:{$gt:60}},{$inc:{"amount":3}})

db.inventory.find({amount:{$gt:60}})

{ "_id" : ObjectId("55a0d1ae742d958e4c44f682"),"name" : "t5", "amount" : 65,"havemoney" : true }

2、$set用法:{$set : {field:value }},将字段的值设置为value

db.inventory.update({amount:{$gt:60}},{$set:{"amount":64}})

db.inventory.find({amount:{$gt:60}})

{ "_id" : ObjectId("55a0d1ae742d958e4c44f682"),"name" : "t5", "amount" : 64,"havemoney" : true }

设置一个新的key:

db.inventory.find({amount:{$eq:60}})

{ "_id" :ObjectId("559f9f085adecff7fdd402b4"), "name" :"t4", "amount" : 60, "havemoney" : true }

db.inventory.update({amount:{$eq:60}},{$set:{tags:["book"]}})

db.inventory.find({amount:{$eq:60}})

{ "_id" :ObjectId("559f9f085adecff7fdd402b4"), "name" :"t4", "amount" : 60, "havemoney" : true,"tags" : [ "book" ] }

3、$unset用法:{$unset:{field:1 }},删除字段

db.inventory.update({amount:{$gt:60}},{$unset:{"havemoney":1}})

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64 }

没看出field:1中1是干什么用的,写其他值也行,反正只要有东西就行


更新数组

4、$push用法:{$push:{field:value }},把value追加到field里面去,field一定要是数组类型才行。如果field不存在,会新增一个数组类型加进去。

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64 }

db.inventory.update({amount:{$gt:60}},{$push:{tags:["food","game"]}})

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ ["food", "game" ] ] }

db.inventory.update({amount:{$gt:60}},{$push:{tags:"book"}})

db.inventory.find({amount:{$gt:60}})

{ "_id" : ObjectId("55a0d1ae742d958e4c44f682"),"name" : "t5", "amount" : 64, "tags" :[ "food", "game", "book" ] }

如果写成{$push:{tags:["food","game","book"]}},会把整个数组更新到已有的tags中,而不是把"book"更新到已有的tags中,要把多个值更新到数组中要使用$pushAll。

5、$pushAll用法:{$pushAll:{field:value_array }},同$push,只是一次可以追加多个元素到一个数组字段内。

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ "food","game", "book" ] }

db.inventory.update({amount:{$gt:60}},{$pushAll:{tags:["car","ball"]}})

db.inventory.find({amount:{$gt:60}})

{ "_id" : ObjectId("55a0d1ae742d958e4c44f682"),"name" : "t5", "amount" : 64, "tags" :[ "food", "game", "book", "car","ball" ] }

6、$addToSet用法:{ $addToSet : {field:value }},增加一个值到数组内,而且只有当这个值不在数组内才增加。

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ "food","game", "book", "car", "ball" ] }

db.inventory.update({amount:{$gt:60}},{$addToSet:{tags:"MMM"}})

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ "food","game", "book", "car", "ball","MMM" ] }

db.inventory.update({amount:{$gt:60}},{$addToSet:{tags:"MMM"}})

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ "food","game", "book", "car", "ball","MMM" ] }

tags:"MMM"只增加了一次,如果写成tags:["MMM"]会增加一个数组到tags中,而不是把"MMM"增加到tags中。

7、$pop用法:删除最后一个值:{$pop : {field : 1 }},删除第一个值:{$pop : { field : -1 }}

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ "food","game", "book", "car", "ball","MMM" ] }

db.inventory.update({amount:{$gt:60}},{$pop:{tags:1}})

db.inventory.find({amount:{$gt:60}})

{ "_id" :ObjectId("55a0d1ae742d958e4c44f682"), "name" :"t5", "amount" : 64, "tags" : [ "food","game", "book", "car", "ball" ] }

$pop只能删除第一个值或者最后一个值,而不论tags:1还是tags:2都一样。

8、$pull用法:{ $pull:{field:value } },从数组field内删除所有等于value的值。

db.inventory.update({amount:{$gt:60}},{$set:{tags:["food","game", "ball", "book", "car","ball"]}})

db.inventory.update({amount:{$gt:60}},{$pull:{tags:"ball"}})

db.inventory.find({amount:{$gt:60}})

{ "_id" : ObjectId("55a0d1ae742d958e4c44f682"),"name" : "t5", "amount" : 64, "tags" :[ "food", "game", "book", "car" ] }

9、$pullAll用法:{ $pullAll : {field : value_array } },可以一次删除数组内多个值。

db.inventory.update({amount:{$gt:60}},{$set:{tags:["food","game","book", "car"]}})

db.inventory.update({amount:{$gt:60}},{$pullAll:{tags:["food","game"]}})

db.inventory.find({amount:{$gt:60}})

{ "_id" : ObjectId("55a0d1ae742d958e4c44f682"),"name" : "t5", "amount" : 64, "tags" :[ "book", "car" ] }; ]}

10、$用法:更新查询条件匹配的自己的值

db.post.insert({"title" :"ABC","comments" :[ { "by" : "joe", "votes" : 4 }, { "by": "jane", "votes" : 7 } ]})

db.post.update( {'comments.by':'joe'},{$inc:{'comments.$.votes':5}}, false, true )

db.post.find()

{ "_id" :ObjectId("55a0e9225349c0da157fd218"), "title" :"ABC", "comments" : [ { "by" : "joe","votes" : 9 }, { "by" : "jane", "votes": 7 } ] }

$inc操作符后,{ "by": "joe", "votes" : 4 }增加5后变成{"by" : "joe", "votes" : 9 }

db.post.insert({"x":[1,2,3,2]})

db.post.update({x:2},{$inc:{"x.$":1}},false,true)

db.post.find()

{ "_id" :ObjectId("55a0ec6b5349c0da157fd21a"), "x" : [ 1, 3, 3, 2 ]}

$只会应用找到的第一个数组项,示例中只有第一个2加1变成3,第二个2没有加1

db.post.insert({x:[1,2,3,4,3,2,3,2,4]})

db.post.update({x:3},{$unset:{"x.$":1}})

db.post.find()

{ "_id" :ObjectId("55a0eb125349c0da157fd219"), "x" : [ 1, 2, null,4, 3, 2, 3, 2, 4 ] }

db.post.update({x:3},{$pull:{x:null}})

db.post.find()

{ "_id" :ObjectId("55a0eb125349c0da157fd219"), "x" : [ 1, 2, 4, 3,2, 3, 2, 4 ] }

$配合$unset使用的时候,会留下一个null的数组项,不过可以用{$pull:{x:null}}删除是null的数组项。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容