Search code examples
arraysnode.jsmongodbmongoosemongoose-populate

mongoose populate nested array with condition for array element


I have an ArticleGroup which contains articles, models look like this

var ArticleGroup = new mongoose.Schema({
    articles:[{type:mongoose.Schema.Types.ObjectId,ref:'Article'}]
})

var Article = new mongoose.Schema({
    rates:[{
        uid:String,
        rate:Number //user's rate number to this article
    }]
})

now A USER (let's call him JACK) want to perform a query to ArticleGroup, populating articles in this group, selecting the rates filed

usually I do this

ArticleGroupModel
    .findById(articleGroupId)
    .populate('articles','rates')
    .select('articles')
    .exec((err, articleGroup) => {
         if (err) return next(err)
         //...
    })

but now I ONLY want JACK's rate if one article has JACK's rate, just return that article like this

{
    _id:"23jrf23orj89p3fwje4",
    rates:[{
        uid:"JACK's uid",
        rate:"JACK's rate number"
    }]
}

if one article has no JACK's rate, the article is still populated, but with an empty rates filed like this

{
     _id:"23jrf23orj89p3fwje4",
     rates:[]
}

Is there any way to do this?


Solution

  • In order to obtain this result you should reconsider your data model with something like this:

    ArticleGroup = new mongoose.Schema
        some details here ...
    
    ArticleRate = new mongoose.Schema
        uid: String
        rate: Number
    
    Article = new mongoose.Schema
        group:
            type: mongoose.Schema.ObjectId
            ref: 'ArticleGroup'
        rates:[ArticleRate]
    

    And perform this kind of query:

    Article
    .find(group: groupId)
    .populate({
       path: 'rates',
       match: { uid: { $in: { JACK_UID } } },
       select: 'rate'
     })
     .exec();
    

    You could find more helpful informations within the Mongoose documentation.