我正在尝试建立一个记录时间表的系统。每天,员工可以针对分配给他们的不同任务记录不同的时间。我的时间表集合中的每个条目都包含一组单独的时间表条目。此集合的样本数据/模式:
[
{
"_id": "5db2c672620ed61854818ccd",
"EmployeeId": "5da9aed442e3070bbd9f7581",
"TimeSheet": [
{
"_id": "5db2c672620ed61854818ccf",
"TaskId": "5db14152e6537a05258bf573",
"Hours": "2.5",
"Remarks": "Test 2.5"
},
{
"_id": "5db2c672620ed61854818cce",
"TaskId": "5db1886ee6537a05258bf575",
"Hours": "11.5",
"Remarks": "Test 11.5"
}
],
"__v": 0
}
]
对于相应的Task集合,数据以以下方式驻留-
[
{
"_id": "5db14152e6537a05258bf573",
"EmployeeId": "5da9aed442e3070bbd9f7581",
"ProjectId": "5db141d9e6537a05258bf574",
"TaskName": "Finish the timesheet page",
"TaskDescription": "Write the front-end and back-end code to allow employees to record their timesheets."
},
{
"_id": "5db1886ee6537a05258bf575",
"EmployeeId": "5da9aed442e3070bbd9f7581",
"ProjectId": "5db141d9e6537a05258bf574",
"TaskName": "Learn Populate",
"TaskDescription": "Learn how MongoDB/Mongoose uses the equivalent of SQL joins"
},
{
"_id": "5db27e3ca2445c05255dbad0",
"EmployeeId": "5da9aed442e3070bbd9f7581",
"ProjectId": "5db141d9e6537a05258bf574",
"TaskName": "Timesheet save API",
"TaskDescription": "Code the API to save a timesheet to the database"
}
]
我正在尝试将任务详细信息(任务名称,任务描述等)添加到每个任务时间表条目中。为此,我尝试在控制器中使用populate()
方法,就像这样-
exports.findByEmployee = (req, res) => {
TimeSheet.find({ EmployeeId: req.query.EmployeeId })
.then(timesheets => {
timesheets.forEach((ts, ts_index) => {
ts.TimeSheet.forEach((item, index) => {
Task.findById(item.TaskId).populate('TaskId').exec((err, taskDetails) => {
item.TaskDetails = taskDetails;
})
});
})
res.send(timesheets);
}).catch(err => {
res.status(500).send({
message: err.message || "Some error occurred while retrieving timesheets."
});
});
}
但是,API响应(用于获取所有时间表)在各个任务时间表部分中都不包含名为TaskDetails
的键。我的猜测是,由于函数调用的异步特性,res.send(timesheets)
部分在其上面的部分没有时间完成之前就被触发了。所以我的问题是,我该如何解决?总而言之,我希望Task集合中的Task详细信息具有按ID链接到Task的每个单独的时间表项。另外,这是使用populate()
的正确方法,还是有一种更好/更简单/更正确的方法可以解决我的问题?
编辑: 有人要求模型,所以这里是任务和时间表:
const mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
const TaskSchema = mongoose.Schema({
EmployeeId: ObjectId,
ProjectId: ObjectId,
TaskName: String,
TaskDescription: String
}, { collection: 'TASK' });
module.exports = mongoose.model('Task', TaskSchema);
const mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
const TimeSheetSchema = mongoose.Schema({
EmployeeId: ObjectId,
Date: Date,
TimeSheet: [
{
TaskId: {
type: ObjectId,
ref: 'TASK'
},
Hours: String,
Remarks: String
}
]
}, { collection: 'EMPLOYEE_TIMESHEET' });
module.exports = mongoose.model('TimeSheet', TimeSheetSchema);
答案 0 :(得分:1)
这里发生了一些事情。 1)TaskId
在Task集合中不存在,因此填充不起作用(也不需要在那里使用)2)您在item
中声明的ts.TimeSheet.forEach()
对象不会在该forEach()循环之外存在,因此向其添加taskDetails
并不会完成任何事情,因为在forEach()循环结束时item
对象会被破坏。
我相信您想要的是这样的东西
exports.findByEmployee = (req, res) => {
try {
// returns just the TimeSheet object from within the TimeSheet collection
// (recommend renaming one of these to avoid confusion!)
TimeSheet.find({ EmployeeId: req.query.EmployeeId }, 'TimeSheet')
// populates TaskId (which I recommend renaming 'Task')
// with the details from the Task collection
.populate('TimeSheet.TaskId')
// executes the query
.exec(timesheets => {
// sends the object once the query has finished executing
res.send(timesheets);
});
} catch (err) {
res.status(500).send({
message: err.message || 'Some error occurred while retrieving timesheets.',
});
}
};
我强烈推荐MDN "Local Library" Express tutorial,以很好地介绍如何使用MongoDB和Mongoose。