我对Mongoose.js感到烦恼 - 我有一个Category模式和一个Projects模式。每个类别可以包含任意数量的项目,每个项目都有type
和relatedProjects
数组,列出具有相同type
的项目。 relatedProjects
字段必须是随机的,并且限制为4 - 但我无法使用Mongoose执行此操作,而是使用lodash将relatedProjects
的整个结果排在模式之外。
这是我正在使用的实例方法:
ProjectSchema.methods.findRelatedProjects = function(callback) {
return this.model('Project')
.where('type').equals(this.type) // find projects with the same type
.where('_id').ne(this._id) // exclude this project from the result set
.select('_id')
.exec(callback);
};
这是我为单个项目获取relatedProjects
的方法(我正在使用的承诺库是when.js):
router.get('/:id', function(req, res) {
var data = {};
when(Project.findOne({ _id: req.params.id }).exec())
.then(function(project) {
data.project = project;
return node.call(data.project.findRelatedProjects.bind(data.project));
})
.then(function(relatedProjects) {
var project = data.project.toObject();
project.relatedProjects = _.first(_.shuffle(relatedProjects), 4);
res.send(project);
})
.catch(function(error) {
res.send(error);
});
});
但是,当我在获取整个集合后尝试填充该字段时,无论是Categories
还是Projects
,我都会遇到麻烦。要么发回的结果都是空的(尽管console.log
'结果会给我正确的数据),或者它会在没有设置relatedProjects
字段的情况下返回。
以下是完全返回空的代码:
router.get('/content.json', function(req, res) {
var data = {};
when(Category.find({}).lean().exec())
.then(function(categories) {
data.categories = categories;
return when.map(categories, function(category, i) {
return when(Project.find({ category: category._id }).exec())
})
.then(function(projects) {
return when.map(projects, function(project, j) {
return node.call(project.findRelatedProjects.bind(project))
.then(function(relatedProjects) {
project.relatedProjects = relatedProjects;
return project;
})
})
});
})
.then(function(categories) {
res.send({ categories: categories });
})
.catch(function(error) {
res.send(error);
});
});
值得注意的是when.map
异步迭代,但我已经尝试定期循环以获得相同的结果。
此代码返回所有数据,但每个relatedProjects
实例完全为空的事实除外。 (console.log(relatedprojects)
给了我正确的数据):
router.get('/content.json', function(req, res) {
var data = {};
when(Category.find({}).populate('projects').lean().exec())
.then(function(categories) {
data.categories = categories;
categories.forEach(function(category) {
category.projects.forEach(function(project) {
Project.findOne({ _id: project.id }, function(error, dbproject) {
dbproject.findRelatedProjects(function(error, relatedprojects) {
project.relatedProjects = relatedprojects;
})
});
});
});
res.send({categories: categories});
})
.catch(function(error) {
res.send(error);
});
});
答案 0 :(得分:0)
有一些问题。其中两个通过重构是一致的。第一个问题是用when.js
包装一个mongoose承诺正在轻微搞砸了。第二个问题是在使用正确的数据填充文档之前调用了res.send
。此代码修复了问题:
router.get('/content.json', function(req, res) {
var data = { categories: [] };
when.map(Category.find({}).exec(), function(category, i) {
data.categories[i] = category;
data.categories[i].projects = [];
return when.map(Project.find({ category: category._id }).exec(), function(project, j) {
data.categories[i].projects[j] = project.toObject();
return node.call(project.findRelatedProjects.bind(project)).then(function(relatedProjects) {
data.categories[i].projects[j].relatedProjects = _.first(_.shuffle(relatedProjects), 4);
});
});
})
.then(function() {
res.send(data);
})
.catch(function(error) {
res.send(error);
});
});