Search code examples
javascriptnode.jsmongodbmongoosemongodb-query

Delete a specific field meeting specific conditions from an object in a collection


I have searched the web for possible solutions. Basically a field needs to be deleted where the id of an object in an array of objects meets a specific condition.

As a newbie to Mongodb I am not sure where exactly to look for relevant examples.

I want to delete the object where id = 0. The language used will be Javascript.

Not quite sure how to go about it though.

Look at the picture below . In red is an id, each registered user will have their own id. Each user will have a cart associated with their id. In the cart is productsInCart-->products which has fields like id, price etc.

So what happens is the users id is selected then the product(object) deleted where the specific product id = 0. The product id is shown with an arrow in the picture and I guess the Object to be deleted would the one at index = 0 also shown by a red arrow. The same could be done with any other Object at index 1 or 2 or anywhere.

I tried using $pull,$unset and the basics found online but the thing is that accessing the product id field requires a very specific command which I am not sure how to write it in Javscript . In sql it would be something Delete Object Where user id = new ObjectId("66a35c99784aa722b15c9801") and product id = 0

enter image description here


Solution

  • Avoid creating nested array fields. This is considered an anti-pattern and introduces unnecessary complexity to the query. Consider keeping just the cart level.

    [
      {
        ...,
        "cart": [
          {
            "product": {
              "id": 0,
              "name": "iPad 11inch",
              "imageUrl": "./images/ipad.jpg",
              "title": "Apples",
              "description": "Apples are <span class=\"label label-info\">25 CHF each</span>",
              "price": 25
            },
            "quantity": 2
          },
          ...
        ]
      }
    ]
    

    You can simplify the query to be like this:

    db.collection.update({
      "cart.product.id": 0
    },
    {
      "$pull": {
        "cart": {
          "product.id": 0
        }
      }
    })
    

    Mongo Playground


    If you need to stick with your current schema, you will need a sophisticated aggregation pipeline. You need to iterate the cart array with $map, then use $filter to iterate through the productsInCart array to perform the filter. Finally, use $mergeObjects to update the result back to cart level.

    db.collection.update({
      "cart.productsInCart.product.id": 0
    },
    [
      {
        "$set": {
          "cart": {
            "$map": {
              "input": "$cart",
              "as": "c",
              "in": {
                "$mergeObjects": [
                  "$$c",
                  {
                    "productsInCart": {
                      "$filter": {
                        "input": "$$c.productsInCart",
                        "as": "p",
                        "cond": {
                          "$ne": [
                            "$$p.product.id",
                            0
                          ]
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ])
    

    Mongo Playground