【问题标题】:MongoDB: Set field value to 10 if less than 10, otherwise increment by oneMongoDB:如果小于 10,则将字段值设置为 10,否则递增 1
【发布时间】:2019-01-20 04:34:53
【问题描述】:

考虑以下代码:

findAndModify({id: id}, undefined, {$inc: {counter: 1}, {$max: {counter: 10})

由于$inc$max 都尝试更新同一个字段,因此失败并出现错误。

但是,如果我想将计数器设置为 10,如果它的值小于 10,如果不是,则将其值增加 1?我如何在一个原子操作中做到这一点?

有没有办法在单个操作中按顺序应用更新?

【问题讨论】:

标签: node.js mongodb mongoose nosql mongodb-query


【解决方案1】:

我认为这不能在一次操作中完成。但是,您可以使用条件语句创建聚合查询,然后在更新中使用。

(async () => {
    try {
        const results = await Model.aggregate([
            { '$match': { 'id': id } },
            { '$project': { 
                'counter': { 
                    '$cond': [
                        { '$lt': ['$counter', 10 ] },
                        10,
                        { '$add': ['$counter', 1 ] }
                    ] 
                }
            } }
        ]).exec();

        const data = results[0];
        const { counter } = data;

        const doc = await Model.findOneAndUpdate({ id },
            { '$set': { counter } },
            { new: true }
        ).exec();

        console.log(doc);
    } 
    catch (err) {
        console.error(err);
    }
})()

对于原子更新,包括一个查询,该查询限制只有 counter 小于给定上限值 10 的文档的增量:

findAndModify(
    {
        'id': id,
        'counter': { '$lt': 10 } 
    }, undefined, 
    { '$inc': { 'counter': 1 } },
    callback
)

【讨论】:

  • @Soggiorno chridam 的原始答案是正确的。对counter 的任何其他更新也应防止其超过 10。
  • @JohnnyHK 是的,他原来的回答是对的。我犯了一个错误,但没有正确地提出问题。编辑使解决方案完全不同。
  • @chridam 谢谢!您对如何使聚合和更新查询原子化以避免并发环境中的竞争条件有什么建议吗?
  • @Soggiorno 请参阅此answer 了解更多信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
相关资源
最近更新 更多