it-swarm.com.de

Mungo bevölkern Unterunterdokument

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 ()?

16
iamjonesy

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.

22
Neil Lunn

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);
});

65
Antenka

Einfacher

Item
  .find({})
  .populate({
    path: 'comments.user',
    model: 'users' }
  })
  .exec(function(err, data){
    if (err) return handleError(err);
    res.json(data);
});
7
steampowered

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
     });
7
jacobedawson

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.

1
Yash Ojha

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)=>{

})
0
Vishal patel