Node.js MongoDB 4.2:按id查找并仅在另一个字段(布尔值)错误时更新该字段,并确定空响应的原因

Node.js MongoDB 4.2:按id查找并仅在另一个字段(布尔值)错误时更新该字段,并确定空响应的原因,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我试图通过其id字段查找文档,然后仅当该字段的值为false时才更新该文档的另一个字段(isLocked)。我只想更新isLockedField MongoDB版本是4.2 我的第一种方法是执行两个查询: 按文档id查找文档。如果未找到任何内容,则抛出NotFoundError 通过执行查询{id:'id',isLocked:false}并返回新文档来查找和更新文档。如果此查询返回空响应,则表示文档已锁定,然后抛出LockedError(423) 然后,我通过同时执行两个查询优化了该方法。在两个

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

MongoDB版本是4.2

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

  • 按文档id查找文档。如果未找到任何内容,则抛出
    NotFoundError
  • 通过执行查询
    {id:'id',isLocked:false}
    并返回新文档来查找和更新文档。如果此查询返回空响应,则表示文档已锁定,然后抛出
    LockedError
    (423)
  • 然后,我通过同时执行两个查询优化了该方法。在两个承诺都解决后,如果对应,则抛出特定错误


    是否有另一个表单只需要对db进行一次查询,并且能够识别,如果返回了空响应,为什么为空(未通过其id找到或因为它被锁定)?

    如果您只想修改
    isLocked
    字段,您可以使用

    它返回以下内容:

    res.n;//匹配的文档数
    res.nModified;//修改的文件数
    
    因此,基本上,无论当前值是什么,您都会尝试将
    isLocked
    更新为
    true

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

    基本上

    const{n,nModified}=wait Model.update({id},{$set:{isLocked:true})
    如果(n==0){
    抛出新错误('NotFound')
    }
    if(n>0&&nModified==0){//或实际上是“if(nModified==0)”,因为如果n没有在前一个条件下抛出,则它应该始终为正
    抛出新错误(“已锁定”)
    }
    
    如果您不想将isLocked更新为true(例如,它不存在或与
    false
    完全不同),则可以使用
    findOneAndUpdate
    并指定聚合管道作为更新参数

    const result=db.collection('yourCollection').findOneAndUpdate(
    {id:'此id'},
    [{$set:{isLocked:{$cond:{if:{$eq:['$isLocked',false]},那么:true,否则:'$isLocked'}]
    )
    如果(result.value==null)返回NotFoundError
    如果(result.value.isLocked)返回LockedError
    
    结果对象的
    -字段包含更新操作之前的文档

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

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

    请参阅:

    您的MongoDB版本是什么?是否只更新
    已锁定的
    或其他字段?@whoami我正在使用mongo 4.2。@TheeSritabtim我只想更新
    已锁定的
    field@JCastilloSilva:仅当该字段的值为false时?你的意思是如果它有
    true
    你不想更新值吗(为什么?还有,
    被锁定的所有值可以容纳什么?很好!我想你可以用
    {$set:{isLocked:true}}
    代替
    {$set:{isLocked:{$cond:{$if:{$eq:['$isLocked',false]},然后:true,否则:'$isLocked'}}}
    如果我们确信
    isLocked
    是布尔值。是的,如果您确定该字段为布尔值,并且即使文档中不存在该字段,也要将其更新为
    true
    。但是如果是这种情况,您也可以跳过$set字段周围的数组,因为这样您就不需要aggregation-framework提供的条件逻辑。更新了答案以处理这两种情况。