【问题标题】:How to delete ($pull) nested array elements with property value null in arrays with more than one element如何在具有多个元素的数组中删除 ($pull) 属性值为 null 的嵌套数组元素
【发布时间】:2022-11-12 15:34:55
【问题描述】:

我想删除 ($pull) 嵌套数组元素,其中元素的属性之一为 null 并且数组具有多个元素。

这是一个例子。在以下集合中,我想删除 Orders 数组中具有 Amount = null 并且 Orders 数组具有多个元素的元素。也就是说,我只想删除OrderId = 12 的元素,而不删除其他元素。

db.TestProducts.insertMany([
    {
        ProductDetails: { "ProductId": 1, Language: "fr" },
        Orders: [
            { "OrderId": 11, "Amount": 200 },
            { "OrderId": 12, "Amount": null }
        ]
    },
    {
        ProductDetails: { "ProductId": 2, Language: "es" },
        Orders: [
            { "OrderId": 13, "Amount": 300 },
            { "OrderId": 14, "Amount": 400 }
        ]
    },
    {
        ProductDetails: { "ProductId": 3, Language: "en" },
        Orders: [
            { "OrderId": 15, "Amount": null }
        ]
    }
]);

以下尝试基于谷歌搜索和一些其他 StackOverflow 答案的组合,例如Aggregate and update MongoDB

db.TestProducts.aggregate(
    [
        { $match: { "Orders.Amount": { "$eq": null } } },
        { $unwind: "$Orders" },
        {
            "$group": {
                "_id": {
                    ProductId: "$ProductDetails.ProductId",
                    Language: "$ProductDetails.Language"
                },"count": { "$sum": 1 }
            }
        },
        { "$match": { "count": { "$gt": 1 } } },
        { "$out": "temp_results" } 
    ],
    { allowDiskUse: true}
);


db.temp_results.find().forEach((result) => {
    db.TestProducts.updateMany({"ProductDetails.ProductId": result._id.ProductId, "ProductDetails.Language": result._id.Language }, 
        { $pull: { "Orders": {"Amount": null } }})
});

这可行,但我想知道是否可以以更简单的方式完成,特别是如果可以删除聚合管道中的数组元素并避免额外的迭代(forEach)。

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    您可以在更新查询中检查这些条件,检查2个条件

    • 金额为空
    • 检查表达式$expr条件是否Orders数组的大小大于1
    db.TestProducts.updateMany({
      "Orders.Amount": null,
      "$expr": {
        "$gt": [{ "$size": "$Orders" }, 1]
      }
    },
    {
      "$pull": {
        "Orders": { "Amount": null }
      }
    })
    

    Playground

    【讨论】:

      【解决方案2】:

      一个例子 一个例子可能会有所帮助:

       let feed = await Feed.findOneAndUpdate(
            {
              _id: req.params.id,
              feeds: {
                $elemMatch: {
                  type: FeedType.Location,
                  locations: {
                    $size: 0,
                  },
                },
              },
            },
            {
              $pull: {
                feeds: { locations: { $size: 0 }, type: FeedType.Location },
              },
            },
            { new: true, multi: true }
          );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-22
        • 2016-04-28
        • 2021-12-11
        • 1970-01-01
        • 2022-07-19
        • 2021-03-24
        • 2020-07-09
        • 2019-06-03
        相关资源
        最近更新 更多