2017-10-19 12 views
2

J'essaie mongoose populate options de requête mais je ne sais pas pourquoi les options de requête ne fonctionne pas.Remplir les options de requête avec Async Waterfall

Je schéma utilisateur:

const mongoose = require('mongoose'); 
const Schema = mongoose.Schema; 

const UserSchema = new Schema(
    { 
    username: { type: String, required: true }, 
    email: { type: String }, 
    name: { type: String }, 
    address: { type: String } 
    }, 
    { timestamps: true } 
); 
module.exports = mongoose.model('User', UserSchema); 

et le schéma d'alimentation:

const mongoose = require('mongoose'); 
const Schema = mongoose.Schema; 

const FeedSchema = new Schema(
    { 
    user: { type: Schema.ObjectId, ref: 'User' }, 
    notes: { type: String, required: true }, 
    trx_date: { type: Date }, 
    status: { type: Boolean, Default: true } 
    }, 
    { timestamps: true } 
); 

FeedSchema.set('toObject', { getters: true }); 

module.exports = mongoose.model('Feed', FeedSchema); 

Je veux trouver tous feed par user id, j'ai utilisé async waterfall comme le code suivant:

async.waterfall([ 
    function(callback) { 
    User 
     .findOne({ 'username': username }) 
     .exec((err, result) => { 
     if (result) { 
      callback(null, result); 
     } else { 
      callback(err); 
     } 
     }); 
    }, 

    function(userid, callback) { 

    // find user's feed 
    Feed 
     .find({}) 
     // .populate('user', {_id: userid._id}) <== this one also doesn't work 
     .populate({ 
     path: 'user', 
     match: { '_id': { $in: userid._id } } 
     }) 
     .exec(callback); 
    } 
], function(err, docs) { 
    if (err) { 
    return next(err); 
    } 

    console.log(docs); 
}); 

Avec le code ci-dessus, j'ai tous les flux, et il semble que l'option de requête ne fonctionne pas du tout, est-ce que je l'ai fait mal?

Toute aide serait appréciée.

Répondre

2

Vous ne savez pas pourquoi vous cherchez à faire correspondre "après" population lorsque la valeur de _id est ce qui est déjà stocké dans la propriété "user" "avant" vous même remplir.

En tant que tel il est vraiment juste une condition simple « requête » à .find() place:

async.waterfall([ 
    (callback) => 
    User.findOne({ 'username': username }).exec(callback), 

    (user, callback) => { 
    if (!user) callback(new Error('not found')); // throw here if not found 
    // find user's feed 
    Feed 
     .find({ user: user._id }) 
     .populate('user') 
     .exec(callback); 
    } 
], function(err, docs) { 
    if (err) { 
    return next(err); 
    } 

    console.log(docs); 
}); 

En gardant à l'esprit bien sûr que le .findOne() renvoie le document en entier, de sorte que vous voulez juste la propriété _id dans la nouvelle question. Notez également que le "jonglage" dans la fonction de cascade initiale n'est pas nécessaire. S'il y a une erreur, il va "échouer rapidement" au rappel de fin, ou passer par le résultat où il ne l'est pas. Delate "non trouvé" à la méthode suivante à la place.

Bien sûr, cela est vraiment pas nécessaire puisque "Promises" ont été autour depuis un certain temps et vous devriez vraiment être de les utiliser:

User.findOne({ "username": username }) 
.then(user => Feed.find({ "user": user._id }).populate('user')) 
.then(feeds => /* do something */) 
.catch(err => /* do something with any error */) 

Ou bien en utilisant $lookup où vous MongoDB le supporte:

User.aggregate([ 
    { "$match": { "username": username } }, 
    { "$lookup": { 
    "from": Feed.collection.name, 
    "localField": "_id", 
    "foreignField": "user", 
    "as": "feeds" 
    }} 
]).then(user => /* User with feeds in array /*) 

Ce qui est un peu différent dans la sortie, et vous pourriez réellement le changer pour se ressembler avec un peu de manipulation, mais cela devrait vous donner l'idée générale.

Il est généralement préférable de laisser le serveur effectuer la jointure au lieu d'émettre plusieurs demandes, ce qui augmente la latence au minimum.

+0

merci beaucoup, ça marche maintenant. J'ai changé mon code pour utiliser Promises comme vous l'avez dit. – metaphor