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

时间:2018-10-12 07:20:12

标签: mongodb mongoose

如何按照以下要求更新mongo文档:

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

如果文档存在:

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

如果文档不存在

  1. 插入新文档。

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

2 个答案:

答案 0 :(得分:1)

我的建议是走以下路径:

db.getCollection('<some-collection>').update(
    { email: 'someguy@email.com' },
    {
        $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: 'someguy@email.com'
    name: "some guy",
    username: someguy,
    tel: '1234'
}

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

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

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: 'someguy@email.com' },
    {
        $set: {
            name: "some guy",
            username: someguy,
            tel: '1234'
        },
        $setOnInsert: {
            createdAt: new Date(),
            updatedAt: new Date()
        }
    },
    { upsert: true }
);

我希望这会有所帮助!

答案 1 :(得分:0)

您无需检索用于更新属性A的文档。您可以使用mongo的update API来进行此操作。请在下面找到伪代码:

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

上面的代码是针对一个属性的,但是我认为您可以弄清楚如何进行扩展。

希望这会有所帮助!