skip to Main Content

I have a nested array, I have to remove the one object , based upon the condition using aggregation

here is the JSON I get from mongodb

{
  "_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,

Based upon the freePreview condition , help me to remove the video object

2

Answers


  1. You need to use double $map operator to iterate through your array of arrays and use $cond along with $$REMOVE to remove value conditionally:

    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.

    Login or Signup to reply.
  2. @mickl’s answer works great. 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.

    Borrowing heavily from @mickl, here’s how you could do that.

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search