Mongoose.js - заполнение свойства каждого элемента в коллекции с результатами метода экземпляра

80
7

У меня есть проблема с Mongoose.js. У меня есть схема категорий и схема проектов. Каждая категория может иметь любое количество проектов, и каждый проект имеет как type и relatedProjects массив проектов, в котором перечислены проекты того же type. Поле relatedProjects должно быть случайным и ограничено 4, но я не мог сделать это с помощью Mongoose и вместо этого сортировать все результаты связанных relatedProjects вне схемы с помощью lodash.

Это метод экземпляра, который я использую:

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 для одного проекта (библиотека обещаний, которую я использую, is.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 поля связанных 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);
});
});

спросил(а) 2014-07-25T16:41:00+04:00 6 лет, 2 месяца назад
1
Решение
104

Было несколько вопросов. Два из них были согласованы посредством рефакторинга. Первая проблема заключается в том, что обертывание обещания мангуста с помощью when.js слегка прикручивает вещи. Вторая проблема заключалась в том, что 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);
});
});

ответил(а) 2014-07-26T01:49:00+04:00 6 лет, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема