MongoDB学习之路 (五):更新操作符(Update Operators).2nd

本文地址:http://www.cnblogs.com/egger/archive/2013/05/01/3053617.html欢迎转载 ,请保留此链接๑•́ ₃•̀๑!

通常文档只会有一部分要更新。利用原子的更新修改器,可以使得这种部分更新极为髙效。更新修改器是种特殊的键,用来指定复杂的更新操作,比如调整、增加或者删除键,还可能是操作数组或者内嵌文档。

字段更新操作符 Field Update Operators

$set

"$set"用来指定一个键的值。如果这个键不存在,则创建它。

我们往下面的一条用户资料添加“兴趣”信息,

db.users.insert({"name":"egger", "age": 28, "sex" : "male"})

运行下面的代码,将该用户的兴趣设置为“读书”并添加至文档中(此时文档中“hobby”键是不存在,该条文档就会创建它):

db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},

{"$set" : {"hobby" :"read"}} )

当想更改用户的兴趣资料时,使用"$set" 然后将要更新的内容作为键“hobby”的值(下面的示例中将数组作为键值):

db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},

{"$set" : {"hobby" :["swimming","basketball"]}} )

用"$set"甚至可以修改键的数据类型

db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},{"$set" : {"sex" :1 }} )

执行结果如下:

使用"$set"修改内嵌文档:

该文档中的作者信息为内嵌文档,我们将其内容全部更改:

db.posts.update({"author.name":"egger"},{"$set":{"author.name":"mongo","author.age":18}})

$unset

从文档中移除指定的键。

若要完全删除键“hobby”,使用“$unset”即可:

db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},{"$unset" : {"hobby" :1 }} )

$inc

"inc"修改器用来增加已有键的值,或者在键不存在时创建一个键。inc"修改器用来增加已有键的值,或者在键不存在时创建一个键。inc就是专门来增加(和减少)数字的。"$inc"只能用于整数、长整数或双精度浮点数。要是用在其他类型的数据上就会导致操作失败。

例如毎次有人访问该博文,该条博文的浏览数就加1,用键"pageviews"保存浏览数信息。

下面使用"$inc”修改器增加"pageviews"的值

db.posts.update({"_id" : ObjectId("5180f1a991c22a72028238e4")}, {"$inc":{"pageviews":1}})

上面执行update时如果将键值设置为n,那么就表示该键的值增加n(n可以为负数)。

db.posts.update({"_id" : ObjectId("5180f1a991c22a72028238e4")}, {"$inc":{"pageviews":-100}})

$rename

语法: {$rename: { : , : , ... } }

$rename操作符可以重命名字段名称,新的字段名称不能和文档中现有的字段名相同。

如果文档中存在A、B字段,将B字段重命名为A,$rename会将A字段和值移除掉,然后将B字段名改为A.

集合students中的一条文档数据:

{ "_id": 1,"nickname": [ "The American Cincinnatus", "The American Fabius"],"cell": "555-555-5555","name": { "first" : "george", "last" : "washington"}

}

将集合中"nickname"字段名重命名为“alias”、"cell"字段名重命名为"mobile":

db.students.update( { _id: 1 }, { $rename: { 'nickname': 'alias', 'cell': 'mobile' } } )

执行下面的更新操作,集合中已存在name字段,将会删除“name”字段,将“alias”字段名重命名为“name”

db.students.update( { _id: 1 }, { $rename: { "alias": "name" } } )

当重命名子文档字段名时需要使用"."操作符,格式:值为该子文档的字段名.子文档中字段名。

db.students.update( { _id: 1 }, { $rename: { "name.first": "name.fname" } } )

执行上面的更新操作将name字段的值中first字段重命名为fname.

$rename操作符也可以将子文档中键值移到其他子文档中。

db.students.update( { _id: 1 }, { $rename: { "name.last": "contact.lname" } } )

我们将名为name的子文档中的last字段,重名为“lname”,同时将其移动到子文档contact中,若contact字段不存在,数据库会新建该字段。

若指定的字段在集合中不存在,$rename操作符将不会有任何影响。

db.students.update( { _id: 1 }, { $rename: { 'wife': 'spouse' } } )

若指定的多个字段在集合中都不存在,$rename操作符将不会有任何影响。

db.students.update( { _id: 1 }, { $rename: { 'wife': 'spouse', 'vice': 'vp',  'office': 'term' } } )

集合中不存在上面语句中指定的wife、vice、office字段,所以上述的更新操作无任何影响。

若指定的多个字段中,有的在集合中存在,有的不存在,$rename操作符执行下列操作:

存在的字段按照上面的规则重命名为新的名称。

不存在的字段对数据无任何影响。

db.students.update( { _id: 1 }, { $rename: { 'wife': 'alias', 'mobile': 'cell' } } )

执行上述更新操作,文档中只有“mobile”字段被替换为“cell”。

upsert

upsert是一种特殊的更新操作,不是一个操作符。(upsert=up[date]+[in]sert

update() 方法的三个参数是upsert,这个参数是个布尔类型,默认是false。当它为true的时候,update方法会首先查找与第一个参数匹配的记录,在用第二个参数更新之,如果找不到与第一个参数匹配的的记录,就会以这个条件和更新文档为基础创建一个新的文档。如果找到了匹配的文档,则正常更新。upsert非常方便,不必预置集合,同一套代码可以既创建又更新文档。

db.users.remove()

db.users.update({age :25}, {$inc :{"age" :3}},true)

db.users.findOne()

我们将users集合清空,执行upsert操作,查询出age字段值为25的文档,然后将该字段值增加3.

由于我们先清空了集合,所以update操作将执行insert操作,先创建一个键“age”的值为25的文档,然后在将这个值增加3,即键“age”的值为28,如图所示.

$setOnInsert

当update方法使用upsert选项执行insert操作时,$setOnInsert操作符给相应的字段赋值。类似sql中update 语句的set。

db.collection.update( ,

{ $setOnInsert: {: , ... } },

{ upsert:true}//{ upsert: true }可以用true替换)

示例:products集合无任何文档,执行下列语句,将插入一条文档"{ "_id" : 1, "defaultQty" : 100 }":

db.products.update(

{ _id:1},

{ $setOnInsert: { defaultQty:100} },

{ upsert:true}

)

若update方法执行的update操作而不是insert操作,那么$setOnInsert操作符将无效。

集合中有如下一条文档:{"_id":1,"defaultQty":100}

下面的update方法将执行update操作:

db.products.update(

{ _id:1},

{ $setOnInsert: { defaultQty:500, inStock:true},

$set: { item:"apple"} },

{ upsert:true}

)

更新结果,$setOnInsert没有任何影响。

数组更新操作符 Array Update Operators

只能用在键值为数组的键上的数组操作。

$ (query)

语法: { ".$" : value }

当对数组字段进行更新时,且没有明确指定的元素在数组中的位置,我们使用定位操作符("$")标识一个元素,数字都是以0开始的。

和update()一起使用:

定位操作符("$")作为第一个匹配查询条件的元素的占位符,也就是在数组中的索引值。

数组字段必须出现查询文档中。

集合students中有两条文档:

{ "_id" : 1, "grades" : [ 78, 88, 88] }

{"_id" : 2, "grades" : [ 88, 90, 92 ] }

执行下列语句创建集合文档数据:

db.students.remove();

db.students.insert({"_id" : 1, "grades" : [ 78, 88, 88] });

db.students.insert({"_id" : 2, "grades" : [ 88, 90, 92 ] });

执行下列操作:

//查询匹配的文档中,数组有2个88,只更新第一个匹配的元素,也就是"grades.1"db.students.update( { _id: 1, grades: 88 }, { $set: { "grades.$" : 82} }) ;//查询文档中没有出现grades字段,查询报错db.students.update( { _id: 2 }, { $set: { "grades.$" : 82 } } );

"$push"修改器

如果指定的键已经存在,会向已有的数组末尾加入一个元素,要是没有就会创建一个新的数组。

下面是一条文章内容的文档数据:

我们将使用"$push"对该文档添加一条评论信息。。

db.posts.update({"title":"MongoDB"},{$push:{"comments":{"name":"egger","content":"thks!"}}})

$push 没有使用双引号。文档将会增加一个"comments"(评论)键且键值是数组类型的。

继续添加一条评论信息,该信息将添加至键值数组的末尾。

db.posts.update({"title":"MongoDB"},{$push:{"comments":{"name":"egger","content":"thks 2!"}}})

$pull

语法:db.collection.update( { field: }, { $pull: { field: } } );

pull操作符移除指定字段值为数组,且匹配pull操作符移除指定字段值为数组,且匹配pull语句声明的查询条件的所有元素。

//插入一条文档db.profiles.insert({ votes: [ 3, 5, 6, 7, 7, 8] });//移除数组中所有元素7db.profiles.update( { votes: 3 }, { $pull: { votes: 7} } );//移除数组中所有大于6的元素db.profiles.update( { votes: 3 }, { $pull: { votes: { $gt: 6} } } );//Result{ votes: [ 3, 5, 6, 8] }

{ votes: [3, 5, 6 ] }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容