当尝试使用 Mongoose 的 findOneAndUpdate 方法更新 MongoDB 文档中的嵌套数组字段时,我遇到了一个令人困惑的问题,更新似乎没有反映在数据库中。
以下是问题的简要总结:
我有一个名为 Screen 的 MongoDB 模式,其中包含一个名为 timeslots 的数组字段。在每个时间段内,都有一个称为席位的嵌套数组,代表电影院中的可用座位。我正在尝试更新特定座位的状态字段以表明它已被预订。尽管在本地成功修改了状态字段,但更新不会保留在数据库中。
下面是我的代码片段:
router.post('/bookTicket', async (req, res) => {
try {
console.log("Book ticket API is triggered");
// Find the screen details
let getDetails = await Screen.findOne({ title: "DemonSlaye" }).lean()
if (!getDetails) {
return res.status(404).send("Screen not found");
}
console.log("Screen details before update:", getDetails);
// Find the seat status and update it
const foundSeat = getDetails.timeslots[0].seats
.filter(seatTypeIterate => seatTypeIterate.type === 'platinum')
.map(silverSeatRows => silverSeatRows.rows)
.flat()
.find(getrow => getrow.rowname === 'H')
.cols[0]
.seats
.find(getSeatId => getSeatId.seat_id === '2');
if (!foundSeat) {
console.log("Seat not found");
return res.status(404).send("Seat not found");
}
console.log("Seat status before update:", foundSeat);
foundSeat.status = "booked";
foundSeat.bookedBy = "userID";
console.log("Updated seat status:", foundSeat);
const hydratedDetails = Screen.hydrate(getDetails);
console.log("Updating document with ID:", getDetails._id);
// Replace the entire JSON document in the database with the updated one
const updatedDocument=await hydratedDetails.save()
console.log("Document updated successfully:", updatedDocument);
res.send(updatedDocument)
// res.send(hydratedDetails); // Sending the updated document as response
} catch (error) {
console.error("Error occurred:", error);
res.status(500).send("An error occurred while booking the ticket.");
}
});
架构:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const screenSchema = new mongoose.Schema({
status: { type: String},
seat_id: { type: String},
bookedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
});
const rowSchema = new mongoose.Schema({
rowname: { type: String, required: true },
cols: [screenSchema] // Array of seats
});
const timeslotSchema = new mongoose.Schema({
seats: [{
type: { type: String, required: true },
rows: [rowSchema], // Array of rows
price: { type: Number, required: true }
}]
});
const movieSchema = new mongoose.Schema({
title: { type: String, required: true },
theatreId: { type: String, required: true },
location: { type: String, required: true },
language: { type: String, required: true },
time: { type: String, required: true },
screenType: { type: String, required: true },
screenName: { type: String, required: true },
timeslots: [timeslotSchema] // Array of timeslots
},
{ strict: false }
);
const Screen = mongoose.model('Screen', screenSchema);
module.exports = Screen;
输出: 我附上了数据库图像,该图像没有更新座位状态:已预订(seat_id:2)
我尝试使用 $set 运算符,但它不起作用
我的问题在于尝试通过修改使用 findOne 检索的文档,然后使用 Mongoose 的 save 方法将其保存回数据库来更新 MongoDB 文档中的嵌套数组字段。虽然这种方法看起来很直观,但它可能会导致意外的行为,因为 Mongoose 的 save 方法可能不会按预期更新嵌套数组。相反,您应该使用 Mongoose 的 findOneAndUpdate 方法,该方法旨在直接在数据库中更新文档,并且可以更有效地处理嵌套数组。
猫鼬
Model.hydrate()
并不像你想象的那样工作。
当你这样做时:
const hydratedDetails = Screen.hydrate(getDetails);
然后
const updatedDocument = await hydratedDetails.save();
这是同一个文档。与您给它加水时相比,没有任何变化,因此没有保存任何东西。
补水后你需要做出改变。所以类似:
const hydratedDetails = Screen.hydrate(getDetails);
hydratedDetails.title = 'Deamon Slayer 2';
const updatedDocument = await hydratedDetails.save();
所以你最好一开始就不要使用
lean()
。
但是,我认为它无论如何都不适合你,因为
foundSeat
是 filter()
和 map()
返回新数组的结果。它是一个新变量,不再是 getDetails
对象的一部分。当您在 foundSeat
上设置新值时,这些更改不会反映在 getDetails
中。
您的问题源于无法选择正确的
timeslots
。您正在使用数组索引(例如 getDetails.timeslots[0].seats
)从数组中选择一个,因为您没有很好地对数据进行建模。您的 timelsots
应由资源标识符(例如 _id
)选择。然后您就可以执行 findOneAndUpdate
查询。