MongoDB - 如何仅在字段不存在时更新字段

问题描述 投票:0回答:3

如何更新满足以下要求的 mongo 文档:

通过电子邮件属性查找文档:

如果文档存在:

  1. 如果检索到的文档和新文档都具有属性 A,则保留属性 A(检索到的文档)。
  2. 如果检索到的文档属性 A 为 null 或未定义或不存在,则使用新对象的属性 A 进行更新。

如果文档不存在

  1. 插入新文档。

findOneAndUpdate
似乎没有传达这三个要求。谢谢。

mongodb mongoose
3个回答
12
投票

我的建议是走以下路:

db.getCollection('<some-collection>').update(
    { email: '[email protected]' },
    {
        $set: {
            name: "some guy",
            username: someguy,
            tel: '1234'
        }
    },
    { upsert: true }
);

检查 upsert 文档: https://docs.mongodb.com/manual/reference/method/db.collection.update/#upsert-option

现在让我们看看您的要求:

3.如果文档不存在,则插入新文档。

是的,如果没有通过电子邮件找到文档,它将插入新文档到集合中。生成的文档将是查找条件 + $set + 自动生成的 _id 的组合,因此它看起来像这样:

{
    _id: ObjectId(...)
    email: '[email protected]'
    name: "some guy",
    username: someguy,
    tel: '1234'
}

2。如果检索到的文档属性 A 为 null 或未定义或不存在,则使用新对象的属性 A 进行更新。

$set
中提供的所有属性都将无条件保留在数据库中,这也涵盖了您更新 null/未定义值的要求

3.如果检索到的文档和新文档都具有属性 A,则保留属性 A(检索到的文档)。

如果新提供的

A
和数据库
A
相同,我们就没有问题。 如果
A
不同,您不想存储新的
A
值吗? 如果您担心空值/未定义值,可以在向 $set 提供对象之前省略它们。 您不想使用新提供的值更新数据库属性的用例是什么? 我看到的一个用例是,如果您正在创建新记录,但不想更新现有记录的该值,则您希望传递
createdAt
。 如果是这种情况,并且您提前知道这些属性,则可以使用
$setOnInsert
更新运算符。 https://docs.mongodb.com/manual/reference/operator/update/#id1

因此您的更新查询可以如下所示:

db.getCollection('<some-collection>').update(
    { email: '[email protected]' },
    {
        $set: {
            name: "some guy",
            username: someguy,
            tel: '1234'
        },
        $setOnInsert: {
            createdAt: new Date(),
            updatedAt: new Date()
        }
    },
    { upsert: true }
);

我希望这有帮助!


3
投票

更新属性A不需要检索文档,可以使用mongo的

update
API来完成。请找到下面的伪代码:

db.<collection>.update({
    "$or": [
        { "PropertyA": { "$exists": false } }, 
        { "PropertyA": null }
    ]
}, {$set: {"PropertyA": "NewValue"}});

上面的代码适用于一个属性,但我认为您可以弄清楚如何扩展它。

希望这有帮助!


0
投票

await Order.updateOne({ _id: item._id }, { $set: { orderNumber:generateRandomNumber(12) }}, { upsert: true });

你可以这样做。

© www.soinside.com 2019 - 2024. All rights reserved.