我正在尝试使用Mongoose更新mongoDB中的模型Cart。在我的购物车模型中,我有2种地图架构类型,分别称为itemsList
和itemsPrices
。我遇到的问题很奇怪,因为当我尝试“结帐”我的购物车时,模型的其他字段将被保存和更新,例如小计,状态等,但是我对两个地图字段所做的更改却没有保持在数据库中。
我已经做的是在我调用购物车对象上的save函数之前,先验证项目是否已更改以及地图是否已修改,并验证其他字段是否实际更新。这很奇怪,因为当我尝试将商品添加到购物车时。在2个地图字段中添加一个值,它们会更新并保留在数据库中。但是,当我尝试删除它们时,它们并没有坚持删除。
我的购物车模型
let CartSchema = new mongoose.Schema({
itemsList: {
type: Map,
of: Number
},
itemsPrices: {
type: Map,
of: Number
},
subtotal: {
type: Number,
default: 0
},
status: {
type: String,
enum: ['open', 'partially-completed', 'completed'],
default: 'open'
},
fulfilled: {
type: Date
}
})
我在Express中的结帐路线
//Checks out a cart
router.put('/api/cart/:id/checkout', (req, res) => {
CartModel.findById(req.params.id)
.then(cart => {
console.log(cart)
let checkedOutCart = checkoutCart(cart)
console.log(checkedOutCart)
cart = checkedOutCart //also tried cart.set(checkedOutCart)
cart.save(function(err, doc) {
if (err) {
return res.status(400).send(err)
}
res.json(doc)
})
})
.catch(err => {
console.log(err)
return res.status(400).json(err)
})
})
我的checkoutCart(cart)函数
function checkoutCart(cart) {
for (const [itemId, quantity] of cart.itemsList) {
console.log(`Trying to purchase item: ${itemId}, Quantity: ${quantity}`)
let leftInCart = purchaseItem(itemId, quantity)
//Not enough inventory to purchase all items
if (leftInCart > 0) {
//Update the quantity of the item with how much is left
cart.itemsList.set(itemId, leftInCart)
} else {
//Remove the item from the prices and quantity lists
cart.itemsList.delete(itemId)
cart.itemsPrices.delete(itemId)
}
}
//Update the carts subtotal (in the case there are still items left) - using 888 to just check that this field actually got updated
cart.subtotal = 888
//Update the carts status
if (cart.itemsList.size > 0) {
cart.status = 'partially-completed'
} else cart.status = 'completed'
return cart
}
这是我的另一个功能addToCart,可以成功更新地图
//Add item to cart
router.put('/api/cart/:id', (req, res) => {
if (req.body) {
CartModel.findById(req.params.id)
.then(cart => {
cart = addToCart(cart, req.body)
cart.save(function(err, doc) {
if (err) {
return res.status(400).send(err)
}
res.json(doc)
})
})
.catch(err => {
console.error(err)
return res.status(400).send(err)
})
} else {
return res.status(404).send('Body is missing.')
}
})
//Updates the cart with a new item
function addToCart(cart, body) {
let itemId = body.itemId
let quantityToAdd = body.quantity || 1
let price = body.price
//If the cart already has the item, increment its quantity
if (cart.itemsList.has(itemId)) {
let currentQuantity = cart.itemsList.get(itemId)
cart.itemsList.set(
itemId,
currentQuantity + quantityToAdd // Add item to the items_list of the cart and its associated price
)
} else {
// Add the item to the cart
cart.itemsList.set(itemId, quantityToAdd)
cart.itemsPrices.set(itemId, price)
}
cart.subtotal = cart.subtotal + quantityToAdd * price
return cart
}
现在,您可以看到两个功能基本上以相同的方式工作。我基本上是对模型返回的购物车对象进行一些更改,然后在对字段进行逻辑处理后,我尝试调用save,并且除2个映射外的每个字段都在checkout调用中更新,但对于addToCart调用。这是结帐调用逻辑(控制台日志)之前和之后的对象。
从数据库收到的购物车的Console.log(购物车)
{ subtotal: 2750,
status: 'open',
_id: 5c3bd0e03858b8f48d2cd3af,
itemsList:
Map {
'5c3bc2e2141303f3207cb646' => 1,
'5c3bc306141303f3207cb647' => 1 },
itemsPrices:
Map {
'5c3bc2e2141303f3207cb646' => 1000,
'5c3bc306141303f3207cb647' => 1750 },
__v: 0 }
购物车的Console.log(checkedOutCart)带有要保存的更新字段
{ subtotal: 0,
status: 'completed',
_id: 5c3bd0e03858b8f48d2cd3af,
itemsList: Map {},
itemsPrices: Map {},
__v: 0 }
现在还有趣的是我的保存功能res.json(doc)
实际上返回了第二个checkedOutCart内容,但实际上并没有将其保存到数据库中。当我致电此购物车的数据库时,我看到了更新的小计,状态,但地图仍然与其中的项目和价格相同(应该为空)。
我不确定自己在做什么错。
更新: 因此,我注意到如果我将itemsList的值更改为仅0而不是从地图中将其删除,它将进行更新。但是,看来我无法用空地图更新它,为什么?
答案 0 :(得分:0)
我认为此问题可能是由于Map
的架构类型引起的。
MongooseMap
是内置Map
类的子类。在这些文档中,我们将互换使用术语“地图”和MongooseMap
。在Mongoose中,地图是使用任意键创建嵌套文档的方法。注意:在Mongoose Maps中,键必须是字符串才能将文档存储在MongoDB中。
所以,在模式中
let CartSchema = new mongoose.Schema({
itemsList: {
type: Map,
of: String //should be string
},
itemsPrices: {
type: Map,
of: String //should be string
},
subtotal: {
type: Number,
default: 0
},
status: {
type: String,
enum: ['open', 'partially-completed', 'completed'],
default: 'open'
},
fulfilled: {
type: Date
}
});