简体   繁体   English

MongoDB 使用聚合根据条件从嵌套 arrays 中删除对象

[英]MongoDB remove objects from nested arrays based up on the condition using aggregation

I have a nested array, I have to remove the one object, based upon the condition using aggregation我有一个嵌套数组,我必须根据使用聚合的条件删除一个 object

here is the JSON I get from mongodb这是我从 mongodb 得到的 JSON

{
  "_id":  "633d275ceb34a28755974032",
  "name": "free",
  "products": [
    {
      "title": "Product 1",
      "phone": [
        {
          "title": "Best Phone 1 ",
          "video": {
            "Location": "https://video.mp4"
          },
          "freePreview": true
        }
      ]
    },
    {
      "title": "Product 2",
      "phone": [
        {
          "title": "Best Phone 2",
          "video": {
            "Location": "https://video.mp4"
          },
          "freePreview": false
        }
      ]
    }
    
  ] 
}

But I need the data like但我需要像这样的数据

{
  "_id":  "633d275ceb34a28755974032",
  "name": "free",
  "products": [
    {
      "title": "Product 1",
      "phone": [
        {
          "title": "Best Phone 1 ",
          "video": {
            "Location": "https://video.mp4"
          },
          "freePreview": true
        }
      ]
    },
    {
      "title": "Product 2",
      "phone": [
        {
          "title": "Best Phone 2",
          "freePreview": false
        }
      ]
    }
    
  ] 
}

In this data "video object" is removed inside the phone array, because of freePreview is false,在此数据中,由于 freePreview 为 false,phone 数组中的“视频对象”被删除,

Based upon the freePreview condition, help me to remove the video object根据freePreview条件,帮我把视频object删掉

You need to use double $map operator to iterate through your array of arrays and use $cond along with $$REMOVE to remove value conditionally:您需要使用双$map运算符遍历 arrays 数组,并使用$cond$$REMOVE有条件地删除值:

db.collection.aggregate([
    {
        $addFields: {
            products: {
                $map: {
                    input: "$products",
                    as: "p",
                    in: {
                        title: "$$p.title",
                        phone: {
                            $map: {
                                input: "$$p.phone",
                                in: {
                                    title: "$$this.title",
                                    freePreview: "$$this.freePreview",
                                    video: {
                                        $cond: {
                                            if: {
                                                $eq: [
                                                    false,
                                                    "$$this.freePreview"
                                                ]
                                            },
                                            then: "$$REMOVE",
                                            else: "$$this.video"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
])

Mongo Playground蒙戈游乐场

Here's a similar example. 这是一个类似的例子。

@mickl's answer works great. @mickl 的回答很有效。 If you want to allow for possible document/schema changes, then rather than specifying the fields to keep explicitly, you could use "$mergeObjects" to keep everything and then only modify what you need.如果您想允许可能的文档/架构更改,那么与其明确指定要保留的字段,不如使用"$mergeObjects"来保留所有内容,然后只修改您需要的内容。

Borrowing heavily from @mickl, here's how you could do that.从@mickl 大量借用,这就是你如何做到这一点。

db.collection.aggregate([
  {
    $addFields: {
      products: {
        $map: {
          input: "$products",
          as: "p",
          in: {
            "$mergeObjects": [
              "$$p",
              {
                phone: {
                  $map: {
                    input: "$$p.phone",
                    in: {
                      "$mergeObjects": [
                        {
                          "$arrayToObject": {
                            "$filter": {
                              "input": {"$objectToArray": "$$this"},
                              "as": "kv",
                              "cond": {"$ne": ["$$kv.k", "video"]}
                            }
                          }
                        },
                        {
                          video: {
                            $cond: {
                              if: {
                                $eq: [
                                  false,
                                  "$$this.freePreview"
                                ]
                              },
                              then: "$$REMOVE",
                              else: "$$this.video"
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Try it on mongoplayground.net .mongoplayground.net上试用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM