Mongoose, sort query by populated field

匿名 (未验证) 提交于 2019-12-03 02:24:01

问题:

As far as I know, it's possible to sort populated docs with Mongoose (source).

I'm searching for a way to sort a query by one or more populated fields.

Consider this two Mongoose schemas :

var Wizard = new Schema({     name  : { type: String } , spells  : { [{ type: Schema.ObjectId, ref: 'Spell' }] } });  var Spell = new Schema({     name    : { type: String } ,   damages : { type: Number } });

Sample JSON:

[{     name: 'Gandalf',     spells: [{             name: 'Fireball',             damages: 20         }] }, {     name: 'Saruman',     spells: [{             name: 'Frozenball',             damages: 10         }] }, {     name: 'Radagast',     spells: [{             name: 'Lightball',             damages: 15         }] }]

I would like to sort those wizards by their spell damages, using something like :

WizardModel   .find({})   .populate('spells', myfields, myconditions, { sort: [['damages', 'asc']] }) // Should return in the right order: Saruman, Radagast, Gandalf

I'm actually doing those sorts by hands after querying and would like to optimize that.

回答1:

Ask yourself(and here are the answers):

What I want? Sort wizards by their spell damage(it should be an aditional field, probably the sum of the spells damage.

What I did: I have sorted the SPELLS of the wizard.

What should you do: Wizard.find({}).sort({ power : 'asc' }) and then populate with spells and do whatever you like. Power is another field in Wizard. You will need it because even if you populate your spells, you will have an array of spells and it won't help you.

Hope this helps.



回答2:

You can implicitly specify only required parameters of populate method:

WizardModel   .find({})   .populate({path: 'spells', options: { sort: [['damages', 'asc']] }})

Have a look at http://mongoosejs.com/docs/api.html#document_Document-populate Here is an example from a link above.

doc .populate('company') .populate({   path: 'notes',   match: /airline/,   select: 'text',   model: 'modelName'   options: opts }, function (err, user) {   assert(doc._id == user._id) // the document itself is passed })


回答3:

Even though this is rather an old post, I'd like to share a solution through the MongoDB aggregation lookup pipeline

The important part is this:

 {       $lookup: {         from: 'spells',         localField: 'spells',         foreignField:'_id',         as: 'spells'       }     },     {       $project: {         _id: 1,         name: 1,         // project the values from damages in the spells array in a new array called damages         damages: '$spells.damages',         spells: {           name: 1,           damages: 1         }       }     },     // take the maximum damage from the damages array     {       $project: {         _id: 1,         spells: 1,         name: 1,         maxDamage: {$max: '$damages'}       }     },     // do the sorting        
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!