猫鼬用子文档值更新子文档数组

时间:2020-05-09 22:44:43

标签: mongodb mongoose mongodb-query aggregation-framework

我有一个像这样的文件:

{
 _id:ObjectId('111'),
 products:[
  {
   _id:ObjectId('aaa'),
   quantity:2,
   price:800
  }
 ]
}

我想通过将其乘以数量字段来更新价格字段,即数量字段(2 * 800),其结果将被更新/分配给价格。 (至此示例价格已更新为1600)。

更新后的文档:

{
 _id:ObjectId('111'),
 products:[
  {
   _id:ObjectId('aaa'),
   quantity:2,
   price:1600  //the updated field by multiplying the initial 800 * 2
  }
 ]
}

我的选择查询如下:

    Shop.findOneAndUpdate(
        { "_id": '111, "products._id": 'aaa' }
    )

我该如何实现?

2 个答案:

答案 0 :(得分:1)

在MongoDB版本> = 4.2上,因为您可以在更新中执行aggregation-pipeline,请尝试以下查询:

Shop.update(
  /** Remember to convert input strings to type `ObjectId()` prior to querying */
  { _id: ObjectId("111"), "products._id": ObjectId("aaa") },
  /** This aggregation pipeline will re-create `products` array,
   *  if condition is met for an object then price will be multiplied & price field is merged to original object & pushed back to `products` array, 
   *  if condition is not met actual object is pushed back to array */
  [
    {
      $set: {
        products: {
          $map: {
            input: "$products",
            in: {
              $cond: [
                { $eq: ["$$this._id", ObjectId("aaa")] },
                {
                  $mergeObjects: [ "$$this", { price: { $multiply: ["$$this.quantity", "$$this.price"] }}]
                },
                "$$this"
              ]
            }
          }
        }
      }
    }
  ]
);

答案 1 :(得分:1)

正如@Casey在评论中建议的那样,您可以分多个步骤进行操作,找到商店,找到产品,更改产品价格,保存商店。

router.patch("/shops/:shopId/:productId", async (req, res) => {
  const { shopId, productId } = req.params;

  let shop = await Shop.findById(shopId);

  if (!shop) return res.status(400).send("Shop not found");

  const productIndex = shop.products.findIndex((p) => p._id.toString() === productId);

  if (productIndex < 0) return res.status(400).send("Product not found in shop");

  let product = shop.products[productIndex];

  product.price *= product.quantity;

  shop = await shop.save();

  res.send(shop);
});

假设您现有的商店中有两种产品:

{
    "_id": "5eb85ab17c2bfb3e2cfc15d0",
    "products": [
        {
            "_id": "5eb85ab17c2bfb3e2cfc15d2",
            "quantity": 2,
            "price": 800
        },
        {
            "_id": "5eb85ab17c2bfb3e2cfc15d1",
            "quantity": 3,
            "price": 500
        }
    ]
}

如果您想使用"_id": "5eb85ab17c2bfb3e2cfc15d2"更新价格,我们会向网址http://your base url/shops/5eb85ab17c2bfb3e2cfc15d0/5eb85ab17c2bfb3e2cfc15d2发送补丁请求

输出将如下所示:

{
    "_id": "5eb85ab17c2bfb3e2cfc15d0",
    "products": [
        {
            "_id": "5eb85ab17c2bfb3e2cfc15d2",
            "quantity": 2,
            "price": 1600  => UPDATED
        },
        {
            "_id": "5eb85ab17c2bfb3e2cfc15d1",
            "quantity": 3,
            "price": 500
        }
    ]
}