如何使用MongoDB/Mongoose中的先前值更新字段 [英] How to update a field using its previous value in MongoDB/Mongoose

查看:598
本文介绍了如何使用MongoDB/Mongoose中的先前值更新字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我有一些看起来像这样的文件:

{
    id: 1
    name: "foo"
}

我想将另一个string附加到当前的name字段值.

我使用Mongoose尝试了以下操作,但没有成功:

Model.findOneAndUpdate({ id: 1 }, { $set: { name: +"bar" } }, ...);

解决方案

您无法引用要更新的文档的值,因此您将需要一个查询来检索文档,而又需要一个查询来更新文档.自2016年以来,对于处于OPEN状态的请求,似乎有一个功能请求. /p>

如果您的集合中包含如下文档:

{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name" : "bar" }

使用MongoDB Shell,您可以执行以下操作:

db.test.find({ name: "bar" }).snapshot().forEach((doc) => {
    doc.name = "foo-" + doc.name;

    db.test.save(doc);
});

文档将按预期更新:

{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name": "foo-bar" }

请注意 .snapshot() 调用. 这样可以确保查询不会多次返回文档,因为由于文档大小的增加,中间的写操作会移动该查询.

将其应用于您的Mongoose示例,如此官方示例所述:

Cat.findById(1, (err, cat) => {
    if (err) return handleError(err);

    cat.name = cat.name + "bar";

    cat.save((err, updatedCat) => {
        if (err) return handleError(err);

        ...
    });
});

值得一提的是,有一个 $concat 运算符在聚合框架中,但是很遗憾,您不能在update查询中使用它.

无论如何,根据您需要执行的操作,可以将其与

然后将使用如下文档创建一个新集合prefixedTest:

{ "_id" : ObjectId("XXX"), "name": "foo-bar" }

仅作为参考,关于同一主题还有另一个有趣的问题,有一些值得阅读的答案:

And I want to append another string to the current name field value.

I tried the following using Mongoose, but it didn't work:

Model.findOneAndUpdate({ id: 1 }, { $set: { name: +"bar" } }, ...);

解决方案

You can't refer to the values of the document you want to update, so you will need one query to retrieve the document and another one to update it. It looks like there's a feature request for that in OPEN state since 2016.

If you have a collection with documents that look like:

{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name" : "bar" }

Using the MongoDB shell, you can do something like this:

db.test.find({ name: "bar" }).snapshot().forEach((doc) => {
    doc.name = "foo-" + doc.name;

    db.test.save(doc);
});

The document will be updated as expected:

{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name": "foo-bar" }

Note the .snapshot() call. This ensures that the query will not return a document multiple times because an intervening write operation moves it due to the growth in document size.

Applying this to your Mongoose example, as explained in this official example:

Cat.findById(1, (err, cat) => {
    if (err) return handleError(err);

    cat.name = cat.name + "bar";

    cat.save((err, updatedCat) => {
        if (err) return handleError(err);

        ...
    });
});

It's worth mentioning that there's a $concat operator in the aggregation framework, but unfortunately you can't use that in an update query.

Anyway, depending on what you need to do, you can use that together with the $out operator to save the results of the aggregation to a new collection.

With that same example, you will do:

db.test.aggregate([{
    $match: { name: "bar" }
}, {
    $project: { name: { $concat: ["foo", "-", "$name"] }}
}, {
    $out: "prefixedTest"
}]);

And a new collection prefixedTest will be created with documents that look like:

{ "_id" : ObjectId("XXX"), "name": "foo-bar" }

Just as a reference, there's another interesting question about this same topic with a few answers worth reading: Update MongoDB field using value of another field

这篇关于如何使用MongoDB/Mongoose中的先前值更新字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆