【Mongo】MongoDB文档的增删改操作

本文详细介绍了MongoDB中数据的插入、删除、更新等基本操作,包括insertOne、insertMany、deleteOne、deleteMany等方法的使用,以及updateOne、updateMany等更新操作的详细说明。文中还特别讲解了数组操作符、$set运算符和upsert更新等高级功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


系列文章索引:
【Mongo】初步认识MongoDB shell
【Mongo】MongoDB文档查询

数据增删

插入 document

单条插入

insertOne()方法可以向数据库中插入一条数据,效果如下:

> db.game.insertOne({name:"monster hunter: rise",orderDate:new Date(),price:298})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("62ba565711721fa1455eb949")
}

此方法会为 document 自动添加一个_id键,_id也可以自己添加,比如这样:

> db.game.insertOne({name:"monster hunter: world",orderDate:new Date(),price:298,_id:1})
{ "acknowledged" : true, "insertedId" : 1 }

多条插入

insertMany()方法可以向数据库中插入一个document数组,效果如下:

> db.game.insertMany([{name:"bayonetta",company:"nintendo",price:318},{name:"nier replicant",company:"square enix",price:180},{name:"the king of fighters xiii",company:"snk corporation",price:28}])
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("62ba596511721fa1455eb94a"),
                ObjectId("62ba596511721fa1455eb94b"),
                ObjectId("62ba596511721fa1455eb94c")
        ]
}

insertMany()方法默认为有序插入,可以通过指定第二个参数的形式允许 mongoDB 重新排列插入的顺序,来提高性能,使用方法如下:

> db.game.insertMany([
...     {name:"fifa 22", price:63, platform:"switch"},
...     {name:"animal crossing: new horizons", price:326, platform:"switch"},
...     {name:"god of war", price:128, platform:"psn"},
...     {name:"it takes two", price:99, platform:"steam"}
... ],{order:false})
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("62ba629011721fa1455eb94d"),
                ObjectId("62ba629011721fa1455eb94e"),
                ObjectId("62ba629011721fa1455eb94f"),
                ObjectId("62ba629011721fa1455eb950")
        ]
}

如果在插入数据过程中发现中间某个数据错误(如:存在相同的_id值),在有序插入中会立即中断程序,而在无序插入中会跳过此条文档,继续插入后边的数据。

注意:insertMany()方法可以将多个document插入到单个集合中。如果在数据导入的场景下,应该使用数据导入工具,因为 MongoDB 能够接受到的消息是有最大长度限制的(4.0.5 版本 MongoDB 最大消息长度是 48MB,如果超过限制,多数驱动程序会将其拆分为多个 48MB 的请求1

删除操作

删除文档(document)

在 MongoDB 中删除文档可以使用方法deleteOne()deleteMany(),使用方法如下:

> db.game.deleteOne({name:"fifa 22"})
{ "acknowledged" : true, "deletedCount" : 1 }
> db.game.deleteMany({platform:"switch"})
{ "acknowledged" : true, "deletedCount" : 2 }

其中,deleteOne()方法用于删除第一个符合条件的文档,deleteMany()方法用于删除所有符合条件的文档。

注意:db.game.deleteMany({})方法会删除集合中的所有文档,慎用

删除集合

drop()方法可以用于删除一个集合,使用方法如下:

db.game.drop();

数据更新

MongoDB 针对更新操作提供了三个方法,分别是updateOne()updateMany()replaceOne()

其中,updateOne()updateMany()用来对已有文档的更新操作,第一个参数为筛选条件,第二个参数为更改描述;replaceOne()方法用于替换匹配的文档,第一个参数为筛选条件,第二个参数是用来替换的新文档。

替换文档

> db.game.replaceOne({_id:1},{name:"monster hunter: world",price:128,platform:"steam"})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

注意:在更新操作中最好使用_id字段或其他唯一字段作为筛选条件,避免出现更新错误的问题

更新运算符

更新运算符是 MongoDB 内置的特殊键,可以用于指定复杂的更新操作,但是不能修改_id的值。

$set 运算符

用于设置一个 key 的值,如果这个 key 不存在,则会创建一组对应的 k-v,使用方法为:

> db.game.updateOne({_id:1},{$set:{company:"capcon"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.updateOne({_id:1},{$set:{company:"capcom"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : "steam",
        "company" : "capcom"
}

$set 运算符支持修改键的类型,如:

> db.game.updateOne({_id:1},{$set:{platform:["steam","psn","xbox"]}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam",
                "psn",
                "xbox"
        ],
        "company" : "capcom"
}

$set运算符同样支持修改内嵌文档中的数据,使用方式为:

> db.game.updateOne({_id:1},{$set:{company:{name:"capcom",region:"日本"}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam",
                "psn",
                "xbox"
        ],
        "company" : {
                "name" : "capcom",
                "region" : "日本"
        }
}
>
> db.game.updateOne({_id:1},{$set:{"company.region":"america"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam",
                "psn",
                "xbox"
        ],
        "company" : {
                "name" : "capcom",
                "region" : "america"
        }
}

$inc 运算符

$inc 运算符用来对数字类型的键进行递增操作,如果该键不存在,则会新建。使用方法如下:

> db.game.updateOne({_id:1},{$inc:{price:2}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 130,
        "platform" : [
                "steam",
                "psn",
                "xbox"
        ],
        "company" : {
                "name" : "capcom",
                "region" : "america"
        }
}
> db.game.updateOne({_id:1},{$inc:{score:5}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 130,
        "platform" : [
                "steam",
                "psn",
                "xbox"
        ],
        "company" : {
                "name" : "capcom",
                "region" : "america"
        },
        "score" : 5
}
> db.game.updateOne({_id:1},{$inc:{score:-3}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 130,
        "platform" : [
                "steam",
                "psn",
                "xbox"
        ],
        "company" : {
                "name" : "capcom",
                "region" : "america"
        },
        "score" : 2
}

注意:$inc 运算符只能操作整型、长整型、双精度浮点型三种类型的数据,如果用在其他类型,会报错。

数组运算符

$push 运算符

$push运算符用于在数组末尾添加一个元素,如果数组不存在,则会自动创建并添加一条数据,以下代码用于在comments数组中添加一条数据

db.game.updateOne(
    { _id: 1 },
    {
        $push: {
            comments: { author: "tom", content: "it is very good" },
        },
    }
);

效果如下:

> db.game.updateOne({_id:1},{$push:{
...     comments:{author:"tom",content:"it is very good"}
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "tom",
                        "content" : "it is very good"
                }
        ]
}
$each 修饰符

$each$push配合使用,可以在一次操作中添加多条数据,以下代码用来新增两条评论

db.game.updateOne(
    { _id: 1 },
    {
        $push: {
            comments: {
                $each: [
                    { author: "link", content: "i can hunt everything" },
                    { author: "salta", content: "link stop~~" },
                ],
            },
        },
    }
);

效果如下:

> db.game.updateOne({_id:1},{$push:{
...     comments:{$each:[
...         {author:"link",content:"i can hunt everything"},
...         {author:"salta",content:"link stop~~"}
...     ]}
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "tom",
                        "content" : "it is very good"
                },
                {
                        "author" : "jerry",
                        "content" : "it is very very good"
                },
                {
                        "author" : "link",
                        "content" : "i can hunt everything"
                },
                {
                        "author" : "salta",
                        "content" : "link stop~~"
                }
        ]
}
$slice 修饰符

$slice修饰符能控制数组只增长到某个长度(如 5),可以防止数据增长过长。如果数组数量超过这个限制长度,则多余的数据不会插入。以下代码用于插入 2 条新评论并限制数组长度不能超过 5

db.game.updateOne(
    { _id: 1 },
    {
        $push: {
            comments: {
                $each: [
                    { author: "kaiya", content: "shabby" },
                    { author: "ying", content: "kaiya laji" },
                ],
                $slice: 5,
            },
        },
    }
);

效果如下:

> db.game.updateOne({_id:1},{$push:{
...     comments:{
...         $each:[
...             {author:"kaiya",content:"shabby"},
...             {author:"ying",content:"kaiya laji"}
...         ],
...         $slice:5
...     }
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "tom",
                        "content" : "it is very good"
                },
                {
                        "author" : "jerry",
                        "content" : "it is very very good"
                },
                {
                        "author" : "link",
                        "content" : "i can hunt everything"
                },
                {
                        "author" : "salta",
                        "content" : "link stop~~"
                },
                {
                        "author" : "kaiya",
                        "content" : "shabby"
                }
        ]
}
$sort 修饰符

$sort用于在截断数组之前对数组进行排序,然后再保留对应的长度,以下代码用来插入后排序:

db.game.updateOne(
    { _id: 1 },
    {
        $push: {
            comments: {
                $each: [
                    { author: "alix", content: "it`s so cool" },
                    { author: "bill", content: "oh my god of war" },
                ],
                $slice: 5,
                $sort: { author: 1 },
            },
        },
    }
);

效果如下:

> db.game.updateOne({_id:1},{$push:{
...     comments:{
...         $each:[
...             {author:"alix",content:"it`s so cool"},
...             {author:"bill",content:"oh my god of war"}
...         ],
...         $slice:5,
...         $sort:{author:1}
...     }
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "alix",
                        "content" : "it`s so cool"
                },
                {
                        "author" : "bill",
                        "content" : "oh my god of war"
                },
                {
                        "author" : "jerry",
                        "content" : "it is very very good"
                },
                {
                        "author" : "link",
                        "content" : "i can hunt everything"
                },
                {
                        "author" : "salta",
                        "content" : "link stop~~"
                }
        ]
}

注意:不能将$sort$slice修饰符单独与$push使用,使用时必须有$each存在

$addToSet 运算符

用于在添加数据时避免重复数据,用法如下:

db.game.updateOne(
    { _id: 1 },
    { $set: { comments: [{ author: "salta", content: "it`s so cool" }] } }
);

db.game.updateOne(
    { _id: 1 },
    {
        $addToSet: {
            comments: { author: "salta", content: "it`s my like" },
        },
    }
);

效果如下:

> //comments数据设置为一条
> db.game.updateOne({_id:1},{$set:{comments:[{author:"salta",content:"it`s so cool"}]}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "it`s so cool"
                }
        ]
}
> //插入一条新数据,新数据其中一个字段不同,可以正常插入
> db.game.updateOne({_id:1},{$addToSet:{
...     comments:{author:"salta",content:"it`s my like"}
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "it`s so cool"
                },
                {
                        "author" : "salta",
                        "content" : "it`s my like"
                }
        ]
}
> //插入和上一次一样的数据,这次不能正常插入,modifiedCount=0
> db.game.updateOne({_id:1},{$addToSet:{     comments:{author:"salta",content:"it`s my like"} }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "it`s so cool"
                },
                {
                        "author" : "salta",
                        "content" : "it`s my like"
                }
        ]
}

$addToSet运算符可以和$each修饰符配合使用,来插入多条数据,使用方法和$push运算符相同。

$pop

$pop运算符可以从数据头部或尾部删除一个元素,具体用法如下:

//先添加数据
db.game.updateOne(
    { _id: 1 },
    {
        $push: {
            comments: {
                $each: [
                    { author: "link", content: "hello salta" },
                    { author: "xilia", content: "shabby" },
                    { author: "ying", content: "oh my kong" },
                ],
            },
        },
    }
);
//从头部删除数据
db.game.updateOne({ _id: 1 }, { $pop: { comments: -1 } });
//从末尾删除数据
db.game.updateOne({ _id: 1 }, { $pop: { comments: 1 } });

效果如下:

> db.game.updateOne({_id:1},{$push:{
...     comments:{$each:[
...         {author:"link",content:"hello salta"},
...         {author:"xilia",content:"shabby"},
...         {author:"ying",content:"oh my kong"}
...     ]}
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "it`s so cool"
                },
                {
                        "author" : "salta",
                        "content" : "it`s my like"
                },
                {
                        "author" : "link",
                        "content" : "hello salta"
                },
                {
                        "author" : "xilia",
                        "content" : "shabby"
                },
                {
                        "author" : "ying",
                        "content" : "oh my kong"
                }
        ]
}
> db.game.updateOne({_id:1},{$pop:{comments:-1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "it`s my like"
                },
                {
                        "author" : "link",
                        "content" : "hello salta"
                },
                {
                        "author" : "xilia",
                        "content" : "shabby"
                },
                {
                        "author" : "ying",
                        "content" : "oh my kong"
                }
        ]
}
> db.game.updateOne({_id:1},{$pop:{comments:1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.updateOne({_id:1},{$pop:{comments:1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "it`s my like"
                },
                {
                        "author" : "link",
                        "content" : "hello salta"
                }
        ]
}
$pull

$pull用于删除数组中所有符合特定条件的元素,以下方法用来删除 comments 数组中含有author:"salta"的所有元素:

db.game.updateOne({ _id: 1 }, { $pull: { comments: { author: "salta" } } });

效果如下:

> db.game.updateOne({_id:1},{$pull:{comments:{author:"salta"}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.findOne({_id:1})
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "link",
                        "content" : "hello salta"
                }
        ]
}

注意:如上例所示,在使用$pull运算符处理对象数组时,如果按对象的某一个属性删除,则只判断这一个属性是否符合条件,其他属性不参与判断

定位运算符($)

$运算符用于对符合筛选条件的第一个文档进行修改,以下代码用于修改 document 的数组元素comments中第一个author=link的元素,改为author=salta

db.game.updateOne(
    { "comments.author": "link" },
    {
        $set: {
            "comments.$.author": "salta",
        },
    }
);

运行效果如下:

> db.game.find({_id:1}).pretty()
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "link",
                        "content" : "hello salta"
                }
        ]
}
> db.game.updateOne({"comments.author":"link"},{$set:{
...     "comments.$.author":"salta"
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.find({_id:1}).pretty()
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "hello salta"
                }
        ]
}

如果已知修改元素在数组中的位置,可以通过数组下标对元素进行修改,以下代码用于对_id=1的文档中comments数组中的第一个元素进行修改:

db.game.updateOne(
    { _id: 1 },
    {
        $set: {
            "comments.0.author": "xilia",
        },
    }
);

运行效果如下:

> db.game.updateOne({_id:1},{$set:{
...     "comments.0.author":"xilia"
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.find({_id:1}).pretty()
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "xilia",
                        "content" : "hello salta"
                }
        ]
}
使用数组过滤器更新

MongoDB3.6 引入了数组过滤器arrayFilters,可以在数组中筛选出符合条件的元素,并对其进行更新。以下代码用于对数组中的元素筛选出author="xilia"的元素,并添加hidden=true数据:

db.game.updateOne(
    { _id: 1 },
    {
        $set: {
            "comments.$[item].hidden": true,
        },
    },
    { arrayFilters: [{ "item.author": "xilia" }] }
);

执行修改之前先添加测试数据:

> db.game.updateOne({_id:1},{$push:{comments:{$each:[{author:"salta"},{author:"link"},{author:"link"}]}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.find({_id:1}).pretty()
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "xilia",
                        "content" : "hello salta"
                },
                {
                        "author" : "salta"
                },
                {
                        "author" : "link"
                },
                {
                        "author" : "link"
                }
        ]
}

运行效果如下:

> db.game.updateOne(
...     {_id:1},
...     {$set:{
...     "comments.$[item].hidden":true
... }},
...     {arrayFilters:[
...     {"item.author":"xilia"}
...     ]}
... )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.find({_id:1}).pretty()
{
        "_id" : 1,
        "name" : "monster hunter: world",
        "price" : 128,
        "platform" : [
                "steam"
        ],
        "comments" : [
                {
                        "author" : "xilia",
                        "content" : "hello salta",
                        "hidden" : true
                },
                {
                        "author" : "salta"
                },
                {
                        "author" : "link"
                },
                {
                        "author" : "link"
                }
        ]
}

upsert 更新

upsert关键字用于updateOne()updateMany()方法的第三个参数,第三个参数是一个选项文档,可以指定选项文档的操作。

upsert表示如果能筛选到匹配的文档,则会对所有匹配的文档进行更新;如果更新筛选条件中找不到所匹配的文档,则会以筛选条件和更新内容为基础,创建一个新的文档。注意,这一流程是原子性的。以下为操作示例:

此操作表示name="god of war"的游戏,涨价 30 元

db.game.updateOne(
    { name: "god of war" },
    {
        $inc: {
            price: 30,
        },
    },
    { upsert: true }
);

运行效果如下:

> db.game.updateOne(
...     {name:"god of war"},
...     {$inc:{
...         price:30
...     }},
...     {upsert:true}
... )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.game.find({name:"god of war"}).pretty()
{
        "_id" : ObjectId("62ba629011721fa1455eb94f"),
        "name" : "god of war",
        "price" : 158,
        "platform" : "psn"
}

删除此文档后再执行效果如下:

# 按名称查询,有一条结果
> db.game.find({name:"god of war"}).pretty()
{
        "_id" : ObjectId("62ba629011721fa1455eb94f"),
        "name" : "god of war",
        "price" : 158,
        "platform" : "psn"
}
# 删除此结果
> db.game.deleteOne({name:"god of war"})
{ "acknowledged" : true, "deletedCount" : 1 }
# 按名称查询,没有结果
> db.game.find({name:"god of war"}).pretty()
# 执行upsert更新
> db.game.updateOne(     {name:"god of war"},     {$inc:{         price:30     }},     {upsert:true} )
{
        "acknowledged" : true,
        "matchedCount" : 0,
        "modifiedCount" : 0,
        "upsertedId" : ObjectId("62bd39540a71331919b6295e")
}
# 再次按名称查询,有一个新的文档
> db.game.find({name:"god of war"}).pretty()
{
        "_id" : ObjectId("62bd39540a71331919b6295e"),
        "name" : "god of war",
        "price" : 30
}

$setOnInsert 运算符

此运算符表示,只有再插入文档数据时才会对字段进行设置,后续更新不会对该字段进行任何更改(类似于create_date)。以下代码作用为:

当存在name="Nioh 2"时以下代码更新失效,如果不存在,则会创建新的数据,新数据可以通过 $set运算符更新,但不能通过$setOnInsert运算符更新

db.game.updateOne(
    { name: "Nioh 2" },
    {
        $setOnInsert: {
            published: new Date(),
        },
    },
    { upsert: true }
);

运行效果如下:

# 不存在数据的前提下,upsert更新
> db.game.updateOne(
...     {name:"Nioh 2"},
...     {$setOnInsert:{
...     published:new Date()
... }},
...     {upsert:true}
... )
{
        "acknowledged" : true,
        "matchedCount" : 0,
        "modifiedCount" : 0,
        "upsertedId" : ObjectId("62bd3d9f0a71331919b6297a")
}
# 查询结果,有一条是数据
> db.game.find({name:"Nioh 2"}).pretty()
{
        "_id" : ObjectId("62bd3d9f0a71331919b6297a"),
        "name" : "Nioh 2",
        "published" : ISODate("2022-06-30T06:07:27.206Z")
}
# 继续按setOnInsert更新
> db.game.updateOne(
...     {name:"Nioh 2"},
...     {$setOnInsert:{
...     published:new Date()
... }},
...     {upsert:true}
... )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }
# 查询结果,时间没变化
> db.game.find({name:"Nioh 2"}).pretty()
{
        "_id" : ObjectId("62bd3d9f0a71331919b6297a"),
        "name" : "Nioh 2",
        "published" : ISODate("2022-06-30T06:07:27.206Z")
}
# 按set更新
> db.game.updateOne(     {name:"Nioh 2"},     {$set:{     published:new Date() }},     {upsert:true} )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
# 查询结果,更新成功
> db.game.find({name:"Nioh 2"}).pretty()
{
        "_id" : ObjectId("62bd3d9f0a71331919b6297a"),
        "name" : "Nioh 2",
        "published" : ISODate("2022-06-30T06:08:30.014Z")
}

save() 辅助函数

save()函数时一个 shell 函数。作用是,在文档不存在时插入文档,在文档存在时更新文档。如果文档中包含_id键,save()函数会执行一次 upsert,否则直接插入数据。用法如下:

db.game.save({
    _id: 2,
    name: "warm snow",
    price: 38,
    platform: "PC",
});

批量更新

批量更新函数updateMany()和单个更新函数updateOne()遵循相同的语法,唯一的区别是,updateMany()将会更新所有匹配的文档,而updateOne()只会更新第一个匹配到的文档。

数据修改后返回结果

findOneAndUpdate()方法用于返回匹配的结果并更新数据,默认返回更新之前的数据,如果将第三个参数的returnNewDocument属性设置为 true,可以返回更新之后的数据。注意,这个方法可以保证更新操作的原子性,在多线程环境中很实用。方法使用举例:

// 返回修改前的数据
db.game.findOneAndUpdate(
    { _id: 2 },
    {
        $set: {
            platform: ["PC", "Steam"],
        },
    },
    { $sort: { name: -1 } }
);

// 返回修改之后的数据
db.game.findOneAndUpdate(
    { _id: 2 },
    {
        $set: {
            platform: ["PC", "Steam"],
        },
    },
    {
        $sort: { name: -1 },
        returnNewDocument: true,
    }
);

运行结果如下:

> db.game.findOneAndUpdate(
...     {_id:2},
...     {$set:{
...         platform:["PC","Steam"]
...     }},
...     {$sort:{name:-1}}
... )
{
        "_id" : 2,
        "name" : "warm snow",
        "price" : 56,
        "platform" : "PC",
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "oh,is very googd"
                }
        ]
}
> db.game.findOneAndUpdate(
...     {_id:2},
...     {$set:{
...         platform:["PC","Steam"]
...     }},
...     {
...         $sort:{name:-1},
...         returnNewDocument:true
...     }
... )
{
        "_id" : 2,
        "name" : "warm snow",
        "price" : 56,
        "platform" : [
                "PC",
                "Steam"
        ],
        "comments" : [
                {
                        "author" : "salta",
                        "content" : "oh,is very googd"
                }
        ]
}

另外,findOneAndReplace()方法和findOneAndUpdate()方法的用法完全相同。findOneAndDelete()方法用来返回删除之前的文档。


  1. Shannon Bradshaw,Eoin Brazi,Kristina Chodorow.MongoDB 权威指南(第三版)[M]. 北京:人民邮电出版社出版,2020:25-26 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵枢织梦人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值