I am trying to increment the number in MongoDB using mongoose. But I start failing right at the query stage. When I // @ts-ignore
it flows silently with no error but the value doesn't update.
The error it throws out is: Type 'number' is not assignable to type 'undefined'
My Schema:
const CartSchema: Schema<Document<ICart>> = new Schema({
clientID: { type: String, required: true },
sourceID: { type: String, required: true },
items: {
id: { type: Types.ObjectId },
amount: { type: Number },
grindHow: { type: String, trim: true },
grind: Boolean,
package: { type: String, trim: true },
price: { type: Number },
productID: { type: String },
productName: { type: String },
totalProduct: { type: Number },
},
source: { type: String, required: true },
}, { collection: "carts", timestamps: true });
CartSchema.virtual('cartTotal').get(function() {
// @ts-ignore
const self: any = this;
if(self.items && self.items.length) {
return self.items.reduce((acc: BigNumber, current: any) => acc.plus(current.totalProduct), new BigNumber(0))
} else {
return 0
}
})
The way I am trying to implement that is:
const item = await CartModel.findOneAndUpdate({ sourceID: clientID, 'items.id': itemID }, { $inc: { 'items.$.amount': 1 }}).lean({ virtuals: true })
I also tried with updateOne
. I thought maybe it's more flexible.
CodePudding user response:
items
is not an array, it is an object. You should access it with items.amount
and NOT with items.$.amount
. Change your query like this:
const item = await CartModel.findOneAndUpdate({ sourceID: clientID, 'items.id': itemID }, { $inc: { 'items.amount': 1 }}).lean({ virtuals: true })
CodePudding user response:
The issue was in two places there.
The issue with my Schema - I described it as an object (Thanks to @Nenad Milosavlievic) The correct Schema is (or close to correct. Any hints on Schema are welcomed):
const CartSchema: Schema<Document<ICart>> = new Schema({
clientID: { type: String, required: true },
sourceID: { type: String, required: true },
items: { type: Array },
source: { type: String, required: true },
}, { collection: "carts", timestamps: true });
and another issue with the way I'm querying for the item. I should have converted the string ID into ObjectId
. I missed that out ...
It should have been like this (plus I need to return the updated value, so I am adding an option { new: true }
):
await CartModel.findOneAndUpdate({ sourceID: clientID, 'items.id': Types.ObjectId(itemID) }, { $inc: { 'items.$.amount': 1 }}, { new: true }).lean({ virtuals: true })