3

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
  • Do you want to delete the data from the document in the collection or just not have it turned in the results? Either way, $map is probably going to be helpful here Commented Oct 6, 2022 at 14:15
  • I just need a result like db.collection.findOne() using aggregation, can you help me in implement, please share a code Commented Oct 6, 2022 at 14:20

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

@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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.