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"
}
}