mongodb 更新数组中的对象,然后使用聚合管道获取总和

k4emjkb1  于 2023-01-01  发布在  Go
关注(0)|答案(1)|浏览(123)

假设我有一个文档设置如下:

//Game
{
number: "001",
players: [
    { 
        _id: ObjectId("123"),
        lives: 0
    },
    { 
        _id: ObjectId("124"),
        lives: 2
    },
    { 
        _id: ObjectId("125"),
        lives: 3
    },
],
totalLives: 5,
}

我想做的是建立一个综合渠道
1.设置特定游戏(使用number)中特定玩家(使用_id)的生命--在本例中更新玩家123
1.更新游戏的totalLives总和
我尝试了类似的方法,直到我意识到(或者更确切地说,我相信)您需要使用aggregate()来使用$sum操作符。

await Games.updateOne(
            {
              number: game.number,
              "player._id": new ObjectId(newPlayer._id),
            },
            {
              $set: {
                "players.$[player].lives": newPlayer.lives,
                totalLives: { $sum: "$players.lives" },
              },
            },
            {
              arrayFilters: [{ "player._id": new ObjectId(newPlayer._id) }],
            }
          )
zsbz8rwp

zsbz8rwp1#

是的,您只能通过聚合管道来实现这一点。

  1. $set-更新players数组。使用$map迭代players数组中的每个元素,当前迭代元素的$mergeObjects包含lives字段,并根据条件赋值(如果不匹配,则使用现有值)。
  2. $set-第1阶段之后的另一阶段,用于将所有players.lives求和为totalLives场。
await Games.updateOne({
  number: game.number,
  "player._id": new ObjectId(newPlayer._id),  
},
[
  {
    $set: {
      players: {
        $map: {
          input: "$players",
          in: {
            $mergeObjects: [
              "$$this",
              {
                lives: {
                  $cond: {
                    if: {
                      $eq: [
                        "$$this._id",
                        new ObjectId(newPlayer._id)
                      ]
                    },
                    then: newPlayer.lives,
                    else: "$$this.lives"
                  }
                }
              }
            ]
          }
        }
      }
    },
    
  },
  {
    $set: {
      totalLives: {
        $sum: "$players.lives"
      }
    }
  }
])

Demo @ Mongo Playground

相关问题