我正在使用mongoose构建一个node.js应用程序,但我现在正试图正确地查询MongoDB ...
我目前有3个MongoDB模型:
Room: {_id, name}
Row: {_id, roomid, name}
Seat: {_id rowid, position, number, status}
1个房间有很多排,1排有很多座位。
我可以使用以下查询获取包含所有行的Room对象:
Room.findOne({ name: req.params.room_name }, { __v: 0 })
.then(room => {
room = room.toObject();
Row.find({ room: new ObjectId(room._id) }, { room: 0, __v: 0 })
.sort({ name: 1 })
.then(rows => {
// current code, not working
// rows.foreach(row => {
// row = row.toObject();
// Seat.find({row: new OBjectId(row._id)})
// .sort({position: 1})
// .then(seats => {
// row.seats = seats;
// })
// .catch(err => console.log(err));
res.json(room);
})
.catch(err => console.log(err));
})
.catch(err => {
console.log(err);
res.status(500).json(err);
});
但是,我无法找到获取每一行座位的解决方案,异步处理在每次尝试时都会破坏我的逻辑。我只尝试了一个for循环,async.waterfall(),Promise.all(),但我每次都失败了。
有人帮忙帮我吗?谢谢!
备注:正如评论和可能的答案所建议的那样,我应该只使用一种模式,我已经有了,但我在更新多个席位时遇到了问题。将进一步研究。
通过正确设置引用ref
并稍微修改模型,您可以更轻松地实现此目的。但是,我将修改您的代码以向您展示如何按照您的方法执行此操作,然后我将在引用的字段上提供mongoose填充的示例:
在进入代码之前,我将用.toObject()
替换文件上的.lean()
调用,这是一种mongoose方法,在查询文档并优化查询之后为你完成,因为它跳过了将MongoDB原始文档转换为Mongoose对象的过程:
// Encapsulate this with try-catch
const room = await Room.findOne({ name: req.params.room_name }, { __v: 0 }).lean().exec()
const rows = await Row.find({ roomid: room._id }, { roomid: 0, __v: 0 }).lean().exec()
// This is a blocking loop
for (let row of rows) {
const seats = await Seat.find({ rowid: row._id }, { rowid:0, __v: 0 }).lean().exec()
row.seats = seats
}
room.rows = rows
res.json(room)
// Close try-catch
现在可以使用Promise.all()
稍微优化for循环,await Promises.all(rows.map(async (row) => {
const seats = await Seat.find({ rowid: row._id }, { rowid:0, __v: 0 }).lean().exec()
row.seats = seats
})
将异步执行每个循环迭代:
const roomModel = mongoose.model('Room', new mongoose.Schema({
name: String,
rows: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Row'
}]
))
让我们通过遵循自然而然地直接向您推荐的推理重新定义您的模型:
1个房间有很多行
然后你可以期望你的房间有一系列行ID,如下所示:
const rowModel = mongoose.model('Row', new mongoose.Schema({
seats: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Seat'
}],
name: String
))
进一步,
1排有很多座位
const seatModel = mongoose.model('Seat', new mongoose.Schema({
position: Number,
number: Number
))
最后你的座椅模型就像下面这样简单:
const room = await Room.findOne({ name: req.params.room_name }, { __v: 0 })
.populate({
path: 'rows',
select: '-__v', // Remove __v field
populate: {
path: 'seats',
select: '-__v' // Remove __v field
}).lean().exec()
res.json(room)
现在查询更简单:
Neill Lunn
如您所见,遵循此方法并正确设计数据模型更为简单。但是,正如mongoose.model('Room', new mongoose.Schema({
name: String,
rows: [{
name: String,
seats: [{
position: Number,
number: Number,
}]
})
在评论中所述,这还不是您期望在MongoDB中设计数据模型的方式。不像你那样定义3个简单的数据模型,最好只为行和席位模式定义带有嵌入式子文档数组的1个模型。与此类似的东西:
qazxswpoi