web-dev-qa-db-fra.com

Mongoose: population profonde (peupler un champ peuplé)

J'ai le modèle Category:

Category:
    ...
    articles: [{type:ObjectId, ref:'Article'}]

Le modèle d'article contient la référence à Account model

Article:
    ...
    account: {type:ObjectId, ref:'Account'}

Ainsi, avec le modèle de la catégorie articles peuplée sera:

{ //category
    articles: //this field is populated
     [ { account: 52386c14fbb3e9ef28000001, // I want this field to be populated
         date: Fri Sep 20 2013 00:00:00 GMT+0400 (MSK),
         title: 'Article 1' } ],
    title: 'Category 1' }

La question est: comment peupler un sous-champ (compte) d'un champ rempli ([articles])? Voici comment je le fais maintenant:

globals.models.Category
    .find
        issue : req.params.id
        null
        sort:
            order: 1
    .populate("articles") # this populates only article field, article.account is not populated
    .exec (err, categories) ->
        console.log categories

Je sais que cela a été discuté ici: Mongoose: peupler un champ peuplé mais aucune solution réelle n'a été trouvée

42
f1nn

Mongoose a maintenant une nouvelle méthode Model.populate pour les associations profondes:

https://github.com/LearnBoost/mongoose/issues/1377#issuecomment-15911112

20
DestyNova

Tout d’abord, mettez à jour Mangouste 3 à 4 puis utilisez le moyen le plus simple pour la population profonde de Mangouste, comme indiqué ci-dessous:

Supposons que vous ayez un schéma de blog dont l'ID utilisateur est l'ID de référence puis, dans Utilisateur, une révision en tant qu'ID de référence pour la révision du schéma. Donc, fondamentalement, vous avez trois schémas: 1. Blog 2. Utilisateur 3. La revue

Et, vous devez interroger à partir d'un blog, quel utilisateur est propriétaire de ce blog et de l'avis de l'utilisateur . Vous pouvez donc interroger votre résultat comme suit: 

<BlogModel>.find({}).populate({path : 'userId', populate : {path : 'reviewId'}}).exec(function (err, res) {

 })
46
techyaura

Remplir à plusieurs niveaux

Supposons que vous ayez un schéma d'utilisateur qui garde une trace des amis de l'utilisateur.

var userSchema = new Schema({
  name: String,
  friends: [{ type: ObjectId, ref: 'User' }]
});

Remplir vous permet d'obtenir la liste des amis d'un utilisateur, mais que se passe-t-il si vous souhaitez également que ses amis soient amis? Spécifiez l'option populate pour indiquer à mangouste de renseigner le tableau d'amis de tous les amis de l'utilisateur:

User.findOne({ name: 'Val' }).populate({
    path: 'friends',
    // Get friends of friends - populate the 'friends' array for every friend
    populate: { path: 'friends' }
});

Référence: http://mongoosejs.com/docs/populate.html#deep-populate

21
Lucas

C'est peut-être un peu trop tard, mais j'ai écrit un plug-in Mongoose pour effectuer une population profonde à n'importe quel niveau imbriqué arbitraire. Avec ce plugin enregistré, vous pouvez renseigner les articles et les comptes de la catégorie avec une seule ligne:

Category.deepPopulate(categories, 'articles.account', cb)

Vous pouvez également spécifier options de remplissage pour contrôler des éléments tels que limit, select... pour chaque chemin d'accès renseigné. Consultez la documentation du plugin pour plus d'informations.

17
Buu Nguyen

Le moyen le plus simple de réaliser cela en 3.6 consiste à utiliser Model.populate.

User.findById(user.id).select('-salt -hashedPassword').populate('favorites.things').exec(function(err, user){
    if ( err ) return res.json(400, err);

    Thing.populate(user.favorites.things, {
        path: 'creator'
        , select: '-salt -hashedPassword'
    }, function(err, things){
        if ( err ) return res.json(400, err);

        user.favorites.things = things;

        res.send(user.favorites);
    });
});
8
chovy

Désolé de faire éclater votre bulle, mais il n'y a pas de solution directement prise en charge pour cela. En ce qui concerne Le numéro de Github n ° 601 , il semble sombre. Selon les notes de version de 3.6 , il semble que les développeurs ont reconnu que le problème était satisfait de la population récursive/profonde manuelle.

Ainsi, dans les notes de publication, la méthode recommandée consiste à imbriquer des appels remplis dans le rappel. Par conséquent, dans votre fonction exec(), utilisez categories.populate pour remplir davantage avant d'envoyer une réponse.

3
Kevin Wang
globals.models.Category.find()
  .where('issue', req.params.id)
  .sort('order')
  .populate('articles')
  .exec(function(err, categories) {

    globals.models.Account.populate(categories, 'articles.account', function(err, deepResults){

      // deepResult is populated with all three relations
      console.log(deepResults[0].articles[0].account);

    });
});

L'exemple suivant est inspiré de la question posée @codephobia et renseigne deux niveaux de nombreuses relations. Commencez par chercher une user, remplissez son tableau de orders connexes et incluez chaque orderDetail.

user.model.findOne()
  .where('email', '***@****.com')
  .populate('orders')
  .exec(function(err, user) {

    orderDetail.model.populate(user, 'orders.orderDetails', function(err, results){

      // results -> user.orders[].orderDetails[] 
    });
});

Cela fonctionne bien dans 3.8.8 mais devrait fonctionner dans 3.6.x.

2
Eat at Joes

Ce concept est profond Population . Ici Calendrier, Abonnement, Utilisateur, Appartement sont des modèles ODM mangouste à différents niveaux

Calendar.find({}).populate({
      path: 'subscription_id',model: 'Subscription',
         populate: {path: 'user_id',model: 'User',
           populate: {path: 'apartment_id',model: 'Apartment',
              populate: {path: 'caterer_nonveg_id',
                          model: 'Caterer'}}}}).exec(function(err,data){ 
                          if(!err){
                             console.log('data all',data)
                           }
                           else{
                             console.log('err err err',err)
                            }
                   });
0