I have a Cart schema in Mongoose including CartItems as an array of objects.
{
_id: string;
items: [
{
product: string;
options: {
size: string;
color: string;
}
quantity: number;
}
]
}
In this case, is it possible to push an item when product and options doesn't match or add quantity when it does?
Here is the code that I have tried which does not work.
Cart.findByIdAndUpdate(_id, {
items: {
$cond: [
{
// Does not work
$elemMatch: {
product,
"options.color": options.color,
"options.size": options.size,
},
},
{
// Should add quantity where it is matched.
},
{
$push: {
product,
productName,
options,
quantity,
},
},
],
},
});
Query
newProduct
is the product you want to add (a js variable) newProduct
and not-exists
*it does 2 array reads, alternative could be to use $reduce
but if you have many products $concatArrays
is slow to be inside a reduce, so this is faster solutions (even if reduce would read the array 1 time only)
*you need a method to do update with pipeline, i don't know if mongoose is updated to support it, we are MongoDB 5 so i guess it will be(java is), in worst case you can useupdateCommand
and call it with runCommand(...)
update({"_id" : "1"},
[{"$set":
{"newProduct":
{"product":"p1",
"options":{"size":"s1", "color":"c1"},
"quantity":1}}},
{"$set":
{"not-exists?":
{"$eq":
[{"$filter":
{"input":"$items",
"cond":
{"$and":
[{"$eq":["$$this.product", "$newProduct.product"]},
{"$eq":["$$this.options.size", "$newProduct.options.size"]},
{"$eq":
["$$this.options.color", "$newProduct.options.color"]}]}}},
[]]}}},
{"$set":
{"items":
{"$cond":
["$not-exists?", {"$concatArrays":["$items", ["$newProduct"]]},
{"$map":
{"input":"$items",
"in":
{"$cond":
[{"$and":
[{"$eq":["$$this.product", "$newProduct.product"]},
{"$eq":
["$$this.options.size", "$newProduct.options.size"]},
{"$eq":
["$$this.options.color", "$newProduct.options.color"]}]},
{"$mergeObjects":
["$$this", {"quantity":{"$add":["$$this.quantity", 1]}}]},
"$$this"]}}}]}}},
{"$unset":["not-exists?", "newProduct"]}])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.