mongodb update操作符之常用字段更新操作符

mongodb中的更新操作符分为 字段更新运算符、数组更新运算符和按位更新运算符三种,本文详细介绍常用的字段更新运算操作符。

以下修饰符可用于更新操作;

例如在db.collection.update()和db.collection.findAndModify()中。

语法如下:

{

   <operator1>: { <field1>: <value1>, ... },

   <operator2>: { <field2>: <value2>, ... },

   ...

}

1. $set

 

说明:

$set操作符将字段的值设置为指定的值,如果该字段不存在,$set将添加一个具有指定值的新字段。

 

语法:

{ $set: { <field1>: <value1>, ... } }

 

注意:若要在嵌入式文档或数组中指定<字段>,请使用点表示法。

1.1. 示例

 

初始化数据:

db.products.insert({

  _id: 100,

  sku: "abc123",

  quantity: 250,

  instock: true,

  reorder: false,

  details: { model: "14Q2", make: "xyz" },

  tags: [ "apparel", "clothing" ],

  ratings: [ { by: "ijk", rating: 4 } ]

})

 

1.1.1. 更新单个对象字段

 

示例:查询_id等于100的条件的文档,使用$set操作符更新quantity字段、details字段和tags字段的值。

db.products.update(

   { _id: 100 },

   { $set:

      {

        quantity: 500,

        details: { model: "14Q3", make: "xyz" },

        tags: [ "coats", "outerwear", "clothing" ]

      }

   }

)

 

更改后查询:

db.products.find({"_id":100}).pretty()

返回结果:

{

"_id" : 100,

"sku" : "abc123",

"quantity" : 500,

"instock" : true,

"reorder" : false,

"details" : {

"model" : "14Q3",

"make" : "xyz"

},

"tags" : [

"coats",

"outerwear",

"clothing"

],

"ratings" : [

{

"by" : "ijk",

"rating" : 4

}

]

}

1.1.2. 更新嵌入文档中的字段

 

示例:查询_id等于100的条件的文档,使用$set操作符更新details对象中的make字段值。

db.products.update(

   { _id: 100 },

   { $set: { "details.make": "zzz" } }

)

更改后查询:

db.products.find({"_id":100}).pretty()

返回结果:

{

"_id" : 100,

"sku" : "abc123",

"quantity" : 500,

"instock" : true,

"reorder" : false,

"details" : {

"model" : "14Q3",

"make" : "zzz"

},

"tags" : [

"coats",

"outerwear",

"clothing"

],

"ratings" : [

{

"by" : "ijk",

"rating" : 4

}

]

}

1.1.3. 更新数组字段

 

示例:查询_id等于100的条件的文档,使用$set操作符更新tags字段中的第二个元素(数组索引为1)和ratings数组的第一个元素(数组索引为0)中的ratings字段的值。

db.products.update(

   { _id: 100 },

   { $set:

      {

        "tags.1": "rain gear",

        "ratings.0.rating": 2

      }

   }

)

更改后查询:

db.products.find({"_id":100}).pretty()

返回结果:

{

"_id" : 100,

"sku" : "abc123",

"quantity" : 500,

"instock" : true,

"reorder" : false,

"details" : {

"model" : "14Q3",

"make" : "zzz"

},

"tags" : [

"coats",

"rain gear",

"clothing"

],

"ratings" : [

{

"by" : "ijk",

"rating" : 2

}

]

}

2. $unset

 

说明:

$unset操作符删除特定字段,如果字段不存在,则$unset不做任何操作。

 

语法:

{ $unset: { <field1>: "", ... } }

2.1. 示例

 

初始化数据:

db.products.insert({

  _id: 100,

  sku: "abc123",

  quantity: 250,

  instock: true,

  reorder: false,

  details: { model: "14Q2", make: "xyz" },

  tags: [ "apparel", "clothing" ],

  ratings: [ { by: "ijk", rating: 4 } ]

})

 

示例:筛选出sku为abc123的记录,并删除quantity和instock字段

db.products.update(

   { sku: "abc123" },

   { $unset: { quantity: "", instock: "" } }

)

 

更改后查询:

db.products.find({"sku":"abc123"}).pretty()

 

返回结果:

{

"_id" : 100,

"sku" : "abc123",

"reorder" : false,

"details" : {

"model" : "14Q3",

"make" : "zzz"

},

"tags" : [

"coats",

"rain gear",

"clothing"

],

"ratings" : [

{

"by" : "ijk",

"rating" : 2

}

]

}

3. $setOnInsert

 

说明:

如果update和findAndModify api的upsert参数为 true时,更新操作导致插入文档,则$setOnInsert将指定的值赋给文档中的字段。如果更新操作没有导致插入,则$setOnInsert不做任何操作。

 

语法:

db.collection.update(

   <query>,

   { $setOnInsert: { <field1>: <value1>, ... } },

   { upsert: true }

)

3.1. 示例

 

初始化数据:

db.products.insert({

  _id: 100,

  sku: "abc123",

  quantity: 250,

  instock: true,

  reorder: false,

  details: { model: "14Q2", make: "xyz" },

  tags: [ "apparel", "clothing" ],

  ratings: [ { by: "ijk", rating: 4 } ]

})

 

示例:筛选出sku为abc123的记录,并删除quantity和instock字段

db.products.update(

  { _id: 100 },

  {

     $set: { item: "apple" },

     $setOnInsert: { defaultQty: 100 }

  },

  { upsert: true }

)

 

更改后查询:

db.products.find({"_id":100}).pretty()

 

返回结果:因为已经存在id为100的文档记录,所以defaultQty字段没有被插入。如果不存在

{id为100的文档记录,则defaultQty字段会被插入

"_id" : 100,

"sku" : "abc123",

"reorder" : false,

"details" : {

"model" : "14Q3",

"make" : "zzz"

},

"tags" : [

"coats",

"rain gear",

"clothing"

],

"ratings" : [

{

"by" : "ijk",

"rating" : 2

}

],

"item" : "apple"

}

4. $rename

 

说明:

更新字段的名称,新字段名称必须与现有字段名称不同。

 

语法:

{$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } }

 

注意:

$rename操作符在逻辑上同时执行旧名称和新名称的$unset操作,然后使用新名称执行$set操作。因此,操作可能不会保留文档中字段的顺序;也就是说,重命名的字段可以在文档中移动。

如果文档中已经有一个<newName>字段,则$rename操作符会删除该字段,并将指定的<field>重命名为<newName>。

如果要重命名的字段在文档中不存在,则$rename不做任何操作。

对于嵌入文档中的字段,$rename操作符可以重命名这些字段,并将字段移入或移出嵌入文档。如果这些字段在数组元素中,$rename不起作用。

4.1. 示例

 

初始化数据:

db.students.insertMany([{

  "_id": 1,

  "alias": [ "The American Cincinnatus", "The American Fabius" ],

  "mobile": "555-555-5555",

  "nmae": { "first" : "george", "last" : "washington" }

},

{

  "_id": 2,

  "alias": [ "My dearest friend" ],

  "mobile": "222-222-2222",

  "nmae": { "first" : "abigail", "last" : "adams" }

},

{

  "_id": 3,

  "alias": [ "Amazing grace" ],

  "mobile": "111-111-1111",

  "nmae": { "first" : "grace", "last" : "hopper" }

}])

 

4.1.1. 重命名单个对象字段

 

示例:nmae字段重命名为name

db.students.updateMany( {}, { $rename: { "nmae": "name" } } )

 

更改后查询:

db.students.find()

返回结果:

{ "_id" : 2, "alias" : [ "My dearest friend" ], "mobile" : "222-222-2222", "name" : { "first" : "abigail", "last" : "adams" } }

{ "_id" : 3, "alias" : [ "Amazing grace" ], "mobile" : "111-111-1111", "name" : { "first" : "grace", "last" : "hopper" } }

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

4.1.2. 重命名嵌入文档中的字段

 

要重命名嵌入文档中的字段,可以使用点表示法调用$rename操作符来引用该字段。如果该字段保留在同一个嵌入文档中,也可以在新名称中使用点符号,如下所示:

 

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

 

更改后查询:

db.students.find({"_id":1})

返回结果:

{ "_id" : 1, "alias" : [ "The American Cincinnatus", "The American Fabius" ], "mobile" : "555-555-5555", "name" : { "last" : "washington", "fname" : "george" } }

5. $inc

 

说明:

将一个字段增加一个指定的值,该操作接受正值和负值。如果该字段不存在,请$inc创建该字段并将该字段设置为指定的值,在null值的字段上使用$inc操作符将产生错误。

 

语法:

{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }

5.1. 示例

 

初始化数据:

db.products.insert({

  _id: 1,

  sku: "abc123",

  quantity: 10,

  metrics: {

    orders: 2,

    ratings: 3.5

  }

})

 

示例:quantity字段值减2,metrics.orders字段值加1

db.products.update(

   { sku: "abc123" },

   { $inc: { quantity: -2, "metrics.orders": 1 } }

)

 

更改后查询:

db.products.find({"sku":"abc123"}).pretty()

 

返回结果:

{

"_id" : 1,

"sku" : "abc123",

"quantity" : 8,

"metrics" : {

"orders" : 3,

"ratings" : 3.5

}

}

6. $currentDate

 

说明:

$currentDate操作符将字段的值设置为当前日期,可以是日期或时间戳。默认类型为Date,如果该字段不存在,则$currentDate将该字段添加到文档中。

 

语法:

{ $currentDate: { <field1>: <typeSpecification1>, ... } }

 

<typeSpecification>可以是:

一个布尔值true,用于将当前日期的字段值设置为日期,或

文档{$type: "timestamp"}或{$type: "date"}显式指定类型。运算符区分大小写,只接受小写的“timestamp”或小写的“date”。

6.1. 示例

 

初始化数据:

db.customers.insertOne(

   { _id: 1, status: "a", lastModified: ISODate("2013-10-02T01:11:18.965Z") }

)

 

示例:将lastModified字段更新为当前日期,增加cancellation.date字段,设置值为当前时间戳,增加cancellation.reason字段,设置值为user request,status字段设置为D

db.customers.updateOne(

   { _id: 1 },

   {

     $currentDate: {

        lastModified: true,

        "cancellation.date": { $type: "timestamp" }

     },

     $set: {

        "cancellation.reason": "user request",

        status: "D"

     }

   }

)

 

更改后查询:

db.customers.find().pretty()

 

返回结果:

{

"_id" : 1,

"status" : "D",

"lastModified" : ISODate("2021-01-21T09:22:56.639Z"),

"cancellation" : {

"date" : Timestamp(1611220976, 1),

"reason" : "user request"

}

}

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

推荐阅读更多精彩内容