Mangoose: population profonde (peupler un champ peuplé)

j'ai Category modèle:

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

modèle Article contient ref Account model .

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

Donc, avec peuplée "151960920 Catégorie" modèle 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' }

les questions sont: comment remplir le sous-champ (Compte) d'un champ peuplé ([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 ça a été discuté ici: Mangouste: Remplir un champ peuplé mais aucune solution réelle n'a été trouvée

36
demandé sur Community 2013-09-18 12:45:39

7 réponses

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

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

19
répondu DestyNova 2014-03-07 14:58:42

tout d'abord, mettre à jour mongoose 3 à 4 et ensuite utiliser la manière la plus simple pour la population profonde dans mongoose comme ci-dessous:

supposez que vous ayez le schéma de Blog ayant l'userId comme ID ref et puis dans L'utilisateur vous avez un certain examen comme Id ref pour L'examen de schéma. Donc en gros, vous avez trois schémas : 1. Blog 2. Utilisateur 3. Revue

et, vous devez interroger à partir de blog, quel utilisateur possède ce blog & l'avis de l'utilisateur. Ainsi, vous pouvez interroger votre résultat :

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

 })
33
répondu techyaura 2016-10-05 15:52:02

Remplissage à travers de multiples niveaux

dites que vous avez un schéma d'utilisateur qui garde la trace des amis de l'utilisateur.

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

Peupler vous permet d'obtenir une liste d'amis d'un utilisateur, mais que faire si vous voulais aussi les amis d'un utilisateur d'amis? Spécifiez l'option populate pour dire à mongoose de peupler le tableau friends 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

18
répondu Lucas 2017-01-12 20:30:15

il pourrait être un peu trop tard, mais j'ai écrit un Mangoose plugin pour effectuer la population profonde à tous les niveaux emboîtés arbitraires. Avec ce plugin enregistré, vous pouvez remplir les articles et comptes de category avec une seule ligne:

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

vous pouvez également spécifier populate options pour contrôler des choses comme limit , select ... pour chaque peuplée chemin. Consultez la documentation du plugin pour en savoir plus information.

17
répondu Buu Nguyen 2014-12-10 19:35:08

la façon la plus facile d'accomplir ceci en 3.6 est d'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
répondu chovy 2015-06-26 12:02:01

désolé de faire éclater votre bulle, mais il n'y a pas de solution directement supportée. Quant à GitHub issue #601 , il semble sombre. Selon le 3.6 notes de version , il semble que les développeurs ont reconnu le problème sont heureux avec manuel recursive/population profonde.

donc d'après les notes de publication, la méthode recommandée est d'insérer les appels peuplés dans le callback, donc dans votre fonction exec() , utilisez categories.populate à remplir avant d'envoyer une réponse.

3
répondu Kevin Wang 2013-10-24 21:56:09
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 s'inspire de la question posée par @codephobia et englobe deux niveaux de nombreuses relations. Tout d'abord fetch a user , peupler son tableau de order et inclure 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 très bien dans 3.8.8 mais devrait fonctionner dans 3.6.x .

2
répondu Eat at Joes 2014-12-06 17:43:10