主要目标:
在调用路由时,我要么得到一个新的,要么更新现有的 CartItem 对象。对象数量和总计在中间件中传递,因此对象总计被重新计算。
Schema 似乎在第一个请求上正确地应用了它的中间件(基于控制台日志)。
但是,如果我发出另一个 http 请求,我只会得到一个更新总数的对象。
这超出了我的理解,我将不胜感激。
架构:
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const Product = require('./Product');
const Cart = require('./Cart');
const refIsValid = require('../middleware/refIsValid');
const cartItemSchema = mongoose.Schema({
name: { type: String },
productRef: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
cartRef: { type: mongoose.Schema.Types.ObjectId, ref: 'Cart', required: true },
price: { type: Number, default: 0 },
imgUrl: { type: String },
amount: { type: Number, required: true },
total: { type: Number, default: 0 },
active: { type: Boolean, default: true },
uniqueName: { type: String, unique: true },
});
cartItemSchema.path('productRef').validate((value, respond) => {
return refIsValid(value, respond, Product);
}, 'Invalid product ref.');
cartItemSchema.path('cartRef').validate((value, respond) => {
return refIsValid(value, respond, Cart);
}, 'Invalid cart ref.');
cartItemSchema.path('price').get(function(num) {
return num.toFixed(2);
});
cartItemSchema.pre('save', async function(next) {
const refCart = await Cart.findById(this.cartRef).lean().exec();
const refProduct = await Product.findById(this.productRef).lean().exec();
const uniqueName = `${refProduct._id}_${refCart._id}`;
this.name = refProduct.name;
this.price = refProduct.price;
this.imgUrl = refProduct.imgUrl;
this.total = (this.price * this.amount).toFixed(2);
this.uniqueName = uniqueName;
next();
});
cartItemSchema.post('findOneAndUpdate', async function(result) {
console.log('TCL: result', result);
await result.save(function(err) {
if (err) {
console.error('ERROR!');
}
});
console.log('TCL: docToUpdate', result);
});
cartItemSchema.plugin(uniqueValidator);
module.exports = mongoose.model('cartItem', cartItemSchema);
控制器:
static async updateOrCreate(req, res, next) {
try {
let { cartRef, productRef, amount } = req.body;
let options = { upsert: true, new: true, setDefaultsOnInsert: true };
// const uniqueName = `${productRef._id}_${cartRef._id}`;
const updateOrCreate = await CartItem.findOneAndUpdate(
{ cartRef: cartRef, productRef: productRef },
{ amount: amount },
options,
);
if (updateOrCreate) {
const result = await CartItem.findById(updateOrCreate._id);
console.log('TCL: CartItemController -> updateOrCreate -> result', result);
res.status(200).json({
isNew: false,
message: 'item updated',
productItem: result,
});
return;
}
} catch (error) {
error.statusCode = 500;
next(error);
}
}