减少数组字段的子文档中的字段,如果 MongoDB 中不存在则添加该字段

问题描述 投票:0回答:1

我有一个 MongoDb 文档集合,结构如下:

{
  _id: "9f854842-7475-4714-1234-7ac72beef0d9",
  name: "SalesDemo",
  monthlyQuotas: 43,
  userUsages: [
    {
      userId: "user1",
      dailyQuotas: 6
    }
  ],
}

给定一个operatorId和一个userId,我想要实现的是使用

monthlyQuotas
和:
将文档的
_id = operatorId

减1
  • 将同一文档的数组
    dailyQuotas
    中具有
    userId = userId
    的子文档的字段
    userUsages
    减 1(如果存在)
  • 或者,如果不存在,则使用
    userUsages
    userId=userId
     在数组 
    dailyQuotas=9
  • 中创建一个文档

非常重要的是这个操作必须是原子的,因为操作员和用户都可以完成多个并发请求。

是否可以使用 findOneAndUpdate 或聚合管道来完成此任务?该操作返回新的更新文档非常重要,因为我必须验证配额值。

arrays mongodb atomic
1个回答
0
投票

感谢@cmgchess评论,以下查询满足我的要求:

db.collection.findOneAndUpdate(
  {
    _id: "9f854842-7475-4714-1234-7ac72beef0d9",
  },
  [
    {
      $set: {
        monthlyQuotas: {
          $subtract: ["$monthlyQuotas", 1],
        },
        userUsages: {
          $cond: [
            {
              $in: ["user2", "$userUsages.userId"],
            },
            {
              $map: {
                input: "$userUsages",
                in: {
                  $cond: [
                    {
                      $eq: ["$$this.userId", "user2"],
                    },
                    {
                      $mergeObjects: [
                        "$$this",
                        {
                          dailyQuotas: {
                            $subtract: ["$$this.dailyQuotas", 1],
                          },
                        },
                      ],
                    },
                    "$$this",
                  ],
                },
              },
            },
            {
              $concatArrays: [
                "$userUsages",
                [
                  {
                    userId: "user2",
                    dailyQuotas: 9,
                  },
                ],
              ],
            },
          ],
        },
      },
    },
  ],
  {
    returnNewDocument: true,
  }
);
© www.soinside.com 2019 - 2024. All rights reserved.