Подпункт субположения заполнения Mongoose
У меня есть эта настройка в моем MongoDB
Продукты:
title: String
comments: [] // of objectId's
Комментарии:
user: ObjectId()
item: ObjectId()
comment: String
Здесь моя схема Mongoose:
itemSchema = mongoose.Schema({
title: String,
comments: [{ type: Schema.Types.ObjectId, ref: 'comments' }],
});
Item = mongoose.model('items', itemSchema);
commentSchema = mongoose.Schema({
comment: String,
user: { type: Schema.Types.ObjectId, ref: 'users' },
});
Comment = mongoose.model('comments', commentSchema);
Здесь я получаю свои предметы вместе с комментариями:
Item.find({}).populate('comments').exec(function(err, data){
if (err) return handleError(err);
res.json(data);
});
Как заполнить массив комментариев соответствующим пользователем? Поскольку каждый комментарий имеет пользователь ObjectId()?
Ответы
Ответ 1
Как полный пример вызова, заполняющего объекты результата:
Item.find({}).populate("comments").exec(function(err,data) {
if (err) return handleError(err);
async.forEach(data,function(item,callback) {
User.populate(item.comments,{ "path": "user" },function(err,output) {
if (err) throw err; // or do something
callback();
});
}, function(err) {
res.json(data);
});
});
Вызов .populate()
в форме, выведенной из модели, принимает в качестве первого аргумента документ или массив. Таким образом, вы просматриваете возвращаемые результаты для каждого элемента и вызываете их таким образом в каждом массиве "комментарии". "Путь" сообщает функции, что она соответствует.
Это выполняется с использованием "async" версии forEach, поэтому она не блокируется, но, как правило, после всех манипуляций все элементы ответа не только заполняются комментариями, но и сами комментарии имеют соответствующий "пользователь", подробности.
Ответ 2
Еще один способ (проще) сделать это:
Item
.find({})
.populate({
path: 'comments',
populate: { path: 'user',
model: 'users' }
})
.exec(function(err, data){
if (err) return handleError(err);
res.json(data);
});
Ответ 3
Simpler
Item
.find({})
.populate({
path: 'comments.user',
model: 'users' }
})
.exec(function(err, data){
if (err) return handleError(err);
res.json(data);
});
Ответ 4
Чтобы добавить один последний метод, который люди могут использовать для выбора только определенных полей из поддокументов, вы можете использовать следующий синтаксис "select":
Model.findOne({ _id: 'example' })
.populate({
path: "comments", // 1st level subdoc (get comments)
populate: { // 2nd level subdoc (get users in comments)
path: "user",
select: 'avatar name _id'// space separated (selected fields only)
}
})
.exec((err, res) => {
// etc
});
Ответ 5
Для заполнения вложенного документа и заполнения из нескольких схем
ProjectMetadata.findOne({id:req.params.prjId})
.populate({
path:'tasks',
model:'task_metadata',
populate:{
path:'assigned_to',
model:'users',
select:'name employee_id -_id' // to select fields and remove _id field
}
})
.populate({
path:'client',
model:'client'
})
.populate({
path:'prjct_mgr',
model:'users'
})
.populate({
path:'acc_exec',
model:'users'
})
.populate({
path:'prj_type',
model:'project_type'
}).then ( // .. your thing
или вы можете сделать это следующим образом..
ProjectMetadata.findOne({id:req.params.prjId})
.populate(
[{
path:'tasks',
model:TaskMetadata,
populate:[{
path:'assigned_to',
model:User,
select:'name employee_id'
},
{
path:'priority',
model:Priority,
select:'id title'
}],
select:"task_name id code assign_to stage priority_id"
},
{
path:'client',
model:Client,
select:"client_name"
},
{
path:'prjct_mgr',
model:User,
select:"name"
},
{
path:'acc_exec',
model:User,
select:'name employee_id'
},
{
path:'poc',
model:User,
select:'name employee_id'
},
{
path:'prj_type',
model:ProjectType,
select:"type -_id"
}
])
Я нашел второй метод (с использованием массива) более полезным, когда мне нужно было получить несколько вложенных документов одного и того же родителя.
Ответ 6
попробуйте это найти работу Project и получите связанное с проектом заполнение Task и Perticular Task User find
db.Project.find()
.populate({
path: 'task',
populate: { path: 'user_id'}
})
.exec(async(error,results)=>{
})