Home > database >  How do I findOndAndUpdate an item of an array?
How do I findOndAndUpdate an item of an array?

Time:04-09

This is the update statement:

const cart = await Cart.findOneAndUpdate({
        userId: userId,
        'items._id': itemId,
        'items.product': productId,
        'items.size': size,  
        'items.color': color, 
    }, {
        $set: {
            'items.$.quantity': quantity
        }
    }, {
        new: true
    }).populate({
        path: 'items.product',
        model: 'Product'
    })

This is the new quantity to be applied to the array:

newQuantity {
  itemId: '625065c99edbfad52ac3afce',  
  productId: '6205a4565c0caba6fb39cd5d',
  size: '3',
  quantity: '3',
  color: 'blue2'
}

This is the data in the database, the first item of the array is updated with the new quantity rather than the second item that meets the query criteria shown above.

{
  "_id": {
    "$oid": "623a1f208ea52c030dc331a5"
  },
  "userId": {
    "$oid": "623a1f208ea52c030dc331a3"
  },
  "items": [
    {
      "quantity": 2,
      "product": {
        "$oid": "6205a4565c0caba6fb39cd5d"
      },
      "size": "3",
      "color": "blue1",
      "prodImage": "mom-jeans-3.1.png",
      "_id": {
        "$oid": "625065c69edbfad52ac3afc2"
      }
    },
    {
      "quantity": 1,
      "product": {
        "$oid": "6205a4565c0caba6fb39cd5d"
      },
      "size": "3",
      "color": "blue2",
      "prodImage": "mom-jeans-5.1.png",
      "_id": {
        "$oid": "625065c99edbfad52ac3afce"
      }
    },
    {
      "quantity": 1,
      "product": {
        "$oid": "6205a4565c0caba6fb39cd5d"
      },
      "size": "3",
      "color": "blue3",
      "prodImage": "mom-jeans-4.1.png",
      "_id": {
        "$oid": "625065cc9edbfad52ac3afdc"
      }
    }
  ],
      "__v": 0
    }

CodePudding user response:

'$' operator only update the first element found.

You should use $[] operator:

const cart = await Cart.findOneAndUpdate({
    userId: userId,
    'items._id': itemId,
    'items.product': productId,
    'items.size': size,  
    'items.color': color, 
}, {
    $set: {
        'items.$[].quantity': quantity
    }
}, {
    new: true
}).populate({
    path: 'items.product',
    model: 'Product'
})

Try it.

CodePudding user response:

You can use array filters to get the desired output:

The userId into find query will filter across all documents, and the array filter will find the object in the array which match your condition.

db.collection.update({
  "userId": userId
},
{
  "$set": {
    "items.$[item].quantity": quantity
  }
},
{
  "arrayFilters": [
    {
      "item._id": itemId,
      "item.product": productId,
      "item.size": size,
      "item.color": color
    }
  ]
})

Example here

  • Related