Yangxiao Ou Yangxiao Ou - 1 month ago 13
Node.js Question

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?

Answer

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.