mongodb中的条件更新

时间:2013-10-08 23:45:37

标签: mongodb mongoose

我在下面有以下架构,需要进行更新,详情如下。不确定如何去做。

UserPromo = new Schema
  sendFBInvite:
    earnedIntros:
      type: Number
      default: 0
    earningActionCounter:
      type: Number
      default: 0
    actions:
      type: Number
      default:1
  earnings:
    earnedIntros:
      type: Number
      default: 0
    usedIntros:
      type: Number
      default: 0

每次sendFBInvite.earningActionCounter转到5我想要sendFBInvite.earnedIntros来增加 和earnings.earnedIntros增加1.同时我想将sendFBInvite.earningActionCounter重置为0

有没有办法在一个电话中执行此操作?提前感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

NO。 MongoDB的核心是在应用程序级别而不是DB中拥有所有业务逻辑。所以简而言之,我认为不可能。

旁注: MongoDB非常快,您可以运行多个选择/查找查询,然后激活和更新。此外,还有findAndModify命令(http://docs.mongodb.org/manual/reference/command/findAndModify/)可供您查看。

答案 1 :(得分:0)

这是旧的,但对于其他人来到这里...早期的答案提到需要在应用程序层执行此操作,这是正确的。这是一个伪代码示例,说明如何安全有效地执行此类更新:

incrementActionCounter() {
    do {
        var tryagain = false
        // do the common action first, but only if it would not reach
        //  the boundary condition (5)
        err = collection("").update(
            {"sendFBInvite.earnedActionCounter": {$ne: 4}}, 
            {$inc:{"sendFBInvite.earnedActionCounter": 1}}
        )
        // 'not found' means that it's likely already at 4... so...
        if err == "not found" {
            // still need a condition here, in case someone else updated
            //  the value behind our back
            err = collection("").update({"sendFBInvite.earnedActionCounter": 4}, { 
                $inc: { 
                    "sendFBInvite.earnedIntros":1, 
                    "earnings.earnedIntros":1
                }, 
                $set:{
                    "sendFBInvite.earnedActionCounter": 0
                }
            })
            // 'not found' here means something changed between our 2 queries
            if err == "not found" {
                tryagain = true;
            } else if isSomeOtherError(err) {
                return err
            }
        }
    } while(tryagain)
}

显然,根据您的需要,您可以限制重试,如果序列失败则只返回错误,但上述内容应解决问题,而不会产生新的边缘情况。