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