skip to Main Content

I have the following document in my cart collection:

{
"_id": {
  "$oid": "6555453298c59137f9cb2ee5"
},
"userId": {
  "$oid": "6555453298c59137f9cb2ee3"
},
"email": "[email protected]",
"items": [
  {
    "quantity": 3,
    "product": {
      "$oid": "655437995bc92c0647deb512"
    },
    "_id": {
      "$oid": "65555277fe01541a2052bd5f"
    }
  },
  {
    "quantity": 1,
    "product": {
      "$oid": "655437995bc92c0647deb513"
    },
    "_id": {
      "$oid": "65555278fe01541a2052bd65"
    }
  }
}

In the items array, I want to increase the quantity by 1 where the product (productId) = 655437995bc92c0647deb512. My increase function is as follows:

exports.increaseProductQuantity = async (req, res) => {
console.log('user.service increaseProductQuantity')
const {productId} = req.body;
console.log('productIdd', productId)
const email = authenticateToken(req, res)

console.log('increaseProductQuantity email', email)
(increaseProductQuantity email logs [email protected])


try {
    await Cart.updateOne({
        "email": email
    }, {
        "$inc": {
            "items.$.quantity": 1
        }
    }, {
        "arrayFilters": [{
            "items.product": productId
        }]
    })

    const cart = await Cart.findOne({
        email: email,
    }).populate({
        path: 'items.product',
        model: 'Products'
    })

    console.log('cart', cart)

    // const newCart = JSON.parse(JSON.stringify(cart));
    // newCart.cartTotal = computeCartTotal(newCart);
    // console.log('newCart', newCart)

    // res.status(201).json(newCart)
} catch (error) {
    console.error(error);
    return res.status(500).send('Problem changing item quantity.')
}

}

I get the error:

MongoServerError: The positional operator did not find the match needed from the query.

2

Answers


  1. Change your updateOne query to match the productId directly:

    await Cart.updateOne(
      {
        "email": email,
        "items.product": productId
      },
      {
        "$inc": {
          "items.$.quantity": 1
        }
      }
    );
    

    Or you could use findOneAndUpdate with the new option to directly retrieve the updated cart:

    const cart = await Cart.findOneAndUpdate(
      { "email": email, "items.product": productId },
      { "$inc": { "items.$.quantity": 1 } },
      { new: true, populate: { path: 'items.product', model: 'Products' } }
    );
    
    Login or Signup to reply.
  2. @eekinci’s answer is correct which it will update the first matching element in the items array via $ by assuming that the product value is unique.

    For your current implementation with arrayFilters, you must apply the filtered positional operator $[<identifier>].

    await Cart.updateOne({
      "email": email
    },
    {
      "$inc": {
        "items.$[item].quantity": 1
      }
    },
    {
      "arrayFilters": [
        {
          "item.product": productId
        }
      ]
    });
    

    Demo @ Mongo Playground

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