MongoDB 4.2:仅当字段为假时才按 id 查找并更新另一个字段(布尔值),并确定空响应的原因



我试图通过文档的id字段查找文档,然后仅在该字段的值为 false 时才更新该文档的另一个字段(isLocked(。我只想更新isLockedField.

MongoDB版本是4.2。

我的第一个方法是执行 2 个两个查询:

  1. 按 ID 查找文档。如果什么也没找到,就扔一个NotFoundError
  2. 通过执行查询{ id: 'the-id', isLocked: false }来查找和更新文档,并返回新文档。如果此查询返回空响应,则表示文档已锁定,则抛出LockedError(423(。

然后,我通过同时执行两个查询来优化该方法。在两个承诺解决后,如果对应,则抛出特定错误。

是否有另一种形式只需要对数据库进行一次查询并能够识别,如果返回空响应,为什么为空(未通过其 id 或因为它被锁定而找到(?

如果您不想将isLock更新为true,例如它不存在或与false完全不同,则可以使用findOneAndUpdate并指定聚合管道作为更新参数。

const result = db.collection('yourCollection').findOneAndUpdate(
{ id: 'this-id' },
[{ $set: { isLocked: { $cond: { if: { $eq: ['$isLocked', false] }, then: true, else: '$isLocked' } } } }]
)
if (result.value === null) return NotFoundError
if (result.value.isLocked) return LockedError

结果对象的value字段包含更新操作之前的文档。

如果当字段不存在或包含任何其他数据类型时可以将isLocked设置为 true,则可以删除条件和$set周围的[],从而将其指定为正常更新而不是聚合管道(棘手,我知道(:

const result = db.collection('yourCollection').findOneAndUpdate(
{ id: 'this-id' },
{ $set: { isLocked: true } }
)

请参阅:http://mongodb.github.io/node-mongodb-native/3.5/api/Collection.html#findOneAndUpdate

如果只想修改isLocked字段,可以使用.updateOne()

它返回以下内容:

res.n; // Number of documents matched
res.nModified; // Number of documents modified

因此,基本上无论当前值是多少,您都会尝试将isLocked更新为true

然后,您将检查它是否已被修改。

基本上

const { n, nModified } = await Model.update({ id }, { $set: { isLocked: true } })
if (n === 0) {
throw new Error(‘NotFound’)
}
if (n > 0 && nModified === 0) { // or actually "if (nModified === 0)" because n should always be positive if it did not throw at the previous condition
throw new Error(‘Locked’)
}

最新更新