Ответ 1
Mongoose 4.5 поддерживает этот
Project.find(query)
.populate({
path: 'pages',
populate: {
path: 'components',
model: 'Component'
}
})
.exec(function(err, docs) {});
Как я могу заполнить "компоненты" в документе примера:
{
"__v": 1,
"_id": "5252875356f64d6d28000001",
"pages": [
{
"__v": 1,
"_id": "5252875a56f64d6d28000002",
"page": {
"components": [
"525287a01877a68528000001"
]
}
}
],
"author": "Book Author",
"title": "Book Title"
}
Это мой JS, где я получаю документ Mongoose:
Project.findById(id).populate('pages').exec(function(err, project) {
res.json(project);
});
Mongoose 4.5 поддерживает этот
Project.find(query)
.populate({
path: 'pages',
populate: {
path: 'components',
model: 'Component'
}
})
.exec(function(err, docs) {});
Это работает для меня:
Project.find(query)
.lean()
.populate({ path: 'pages' })
.exec(function(err, docs) {
var options = {
path: 'pages.components',
model: 'Component'
};
if (err) return res.json(500);
Project.populate(docs, options, function (err, projects) {
res.json(projects);
});
});
Документация: Model.populate
Как уже отмечалось, Mongoose 4
поддерживает это. Очень важно отметить, что вы можете проходить глубже, чем один уровень, если это необходимо, хотя это не указано в документации:
Project.findOne({name: req.query.name})
.populate({
path: 'threads',
populate: {
path: 'messages',
model: 'Message',
populate: {
path: 'user',
model: 'User'
}
}
})
Вы можете заполнить несколько вложенных документов, как это.
Project.find(query)
.populate({
path: 'pages',
populate: [{
path: 'components',
model: 'Component'
},{
path: 'AnotherRef',
model: 'AnotherRef',
select: 'firstname lastname'
}]
})
.exec(function(err, docs) {});
Я нашел, что это очень полезно, создавая feathersjs до hook, чтобы заполнить соотношение 2 ref level deep. Модели мангуста просто имеют
tables = new Schema({
..
tableTypesB: { type: Schema.Types.ObjectId, ref: 'tableTypesB' },
..
}
tableTypesB = new Schema({
..
tableType: { type: Schema.Types.ObjectId, ref: 'tableTypes' },
..
}
то в feathersjs перед hook:
module.exports = function(options = {}) {
return function populateTables(hook) {
hook.params.query.$populate = {
path: 'tableTypesB',
populate: { path: 'tableType' }
}
return Promise.resolve(hook)
}
}
Так просто по сравнению с некоторыми другими методами, которые я пытался достичь.
Вы можете сделать это, используя агрегацию $lookup
и, вероятно, лучший способ, поскольку в настоящее время заполнение вымирает из монго
Project.aggregate([
{ "$match": { "_id": mongoose.Types.ObjectId(id) } },
{ "$lookup": {
"from": Pages.collection.name,
"let": { "pages": "$pages" },
"pipeline": [
{ "$match": { "$expr": { "$in": [ "$_id", "$$pages" ] } } },
{ "$lookup": {
"from": Component.collection.name,
"let": { "components": "$components" },
"pipeline": [
{ "$match": { "$expr": { "$in": [ "$_id", "$$components" ] } } },
],
"as": "components"
}},
],
"as": "pages"
}}
])
Я нашел этот вопрос в другом вопросе, который был специфичен для KeystoneJS, но был помечен как дубликат. Если кто-то здесь может искать ответ Keystone, я так и сделал свой глубокий запрос в Keystone.
Mongoose двухуровневая популяция с использованием KeystoneJs [дубликаты]
exports.getStoreWithId = function (req, res) {
Store.model
.find()
.populate({
path: 'productTags productCategories',
populate: {
path: 'tags',
},
})
.where('updateId', req.params.id)
.exec(function (err, item) {
if (err) return res.apiError('database error', err);
// possibly more than one
res.apiResponse({
store: item,
});
});
};
Удалить ссылку документа
if (err) {
return res.json(500);
}
Project.populate(docs, options, function (err, projects) {
res.json(projects);
});
Это сработало для меня.
if (err) {
return res.json(500);
}
Project.populate(options, function (err, projects) {
res.json(projects);
});