Ich habe dieses Setup in meiner MongoDB
Artikel:
title: String
comments: [] // of objectId's
Bemerkungen:
user: ObjectId()
item: ObjectId()
comment: String
Hier ist mein Mongoose-Schema:
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);
Hier bekomme ich meine Artikel zusammen mit den Kommentaren:
Item.find({}).populate('comments').exec(function(err, data){
if (err) return handleError(err);
res.json(data);
});
Wie fülle ich das Kommentar-Array mit seinem jeweiligen Benutzer auf? Da hat jeder Kommentar einen User ObjectId ()?
Als vollständiges Beispiel für das Auffüllen der Ergebnisobjekte:
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);
});
});
Für den Aufruf von .populate()
in dem vom Modell aufgerufenen Formular wird als erstes Argument ein Dokument oder ein Array verwendet. Sie durchlaufen also die zurückgegebenen Ergebnisse für jedes Element, und der Aufruf wird in jedem "Kommentar" -Array auf diese Weise ausgefüllt. Der "Pfad" sagt der Funktion, worauf sie übereinstimmt.
Dies geschieht mit der "async" -Version von forEach, sodass es nicht blockiert wird. Im Allgemeinen werden jedoch nach der Manipulation alle Elemente in der Antwort nicht nur mit Kommentaren gefüllt, sondern die Kommentare selbst haben die entsprechenden "Benutzer" -Details.
Ein weiterer Weg (einfacher), dies zu tun:
Item
.find({})
.populate({
path: 'comments',
populate: { path: 'user',
model: 'users' }
})
.exec(function(err, data){
if (err) return handleError(err);
res.json(data);
});
Einfacher
Item
.find({})
.populate({
path: 'comments.user',
model: 'users' }
})
.exec(function(err, data){
if (err) return handleError(err);
res.json(data);
});
Um eine abschließende Methode hinzuzufügen, die Benutzer möglicherweise verwenden möchten, um nur bestimmte Felder aus Unterdokumenten auszuwählen, können Sie die folgende "select" -Syntax verwenden:
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
});
So füllen Sie ein untergeordnetes Unterdokument und füllen aus mehreren Schemas
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
oder Sie können es auf folgende Weise tun ..
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"
}
])
Ich fand die zweite Methode (Array verwenden) sinnvoller, wenn ich mehrere Unterunterdokumente desselben übergeordneten Elements erhalten musste.
probieren Sie es aus, finden Sie ein Projekt und holen Sie sich die projektbezogene Aufgabensuche und die Benutzersuche für bestimmte Aufgaben
db.Project.find()
.populate({
path: 'task',
populate: { path: 'user_id'}
})
.exec(async(error,results)=>{
})