mongoose,通过填充字段sorting查询

据我所知,可以用Mongoose( source )对填充的文档进行sorting。

我正在寻找一种方法来sorting一个或多个填充字段的查询。

考虑这两个mongoose模式:

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

示例JSON:

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

我想用他们的法术伤害来分类这些巫师,例如:

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

我实际上是在查询后用手去做这些事情,并且想优化它。

问问自己(这里是答案):

我想要的是? 按法术伤害分类巫师(应该是一个附属领域,可能是法术伤害的总和)。

我做了什么:我已经整理了向导的SPELLS。

你应该做什么:Wizard.find({})。sort({power:'asc'}),然后填充咒语,做任何你喜欢的事情。 力量是向导中的另一个领域。 你将需要它,因为即使你填充你的法术,你也会有一系列的法术,它不会帮助你。

希望这可以帮助。

您可以隐式指定填充方法的必需参数:

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

看看http://mongoosejs.com/docs/api.html#document_Document-populate这里是一个上面的链接的例子。

 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 }) 

即使这是一个老的post,我想通过MongoDB聚合查找pipe道共享一个解决scheme

重要的是这样的:

  { $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 { $sort: {'maxDamage' : -1} } 

找一个完整的例子

 'use strict'; const mongoose = require('mongoose'); const Schema = mongoose.Schema; mongoose.connect('mongodb://localhost/lotr'); const db = mongoose.connection; db.on('error', console.error.bind(console, 'connection error:')); db.once('open', () => { let SpellSchema = new Schema({ name : { type: String }, damages : { type: Number } }); let Spell = mongoose.model('Spell', SpellSchema); let WizardSchema = new Schema({ name: { type: String }, spells: [{ type: Schema.Types.ObjectId, ref: 'Spell' }] }); let Wizard = mongoose.model('Wizard', WizardSchema); let fireball = new Spell({ name: 'Fireball', damages: 20 }); let frozenball = new Spell({ name: 'Frozenball', damages: 10 }); let lightball = new Spell({ name: 'Lightball', damages: 15 }); let spells = [fireball, frozenball, lightball]; let wizards = [{ name: 'Gandalf', spells:[fireball] }, { name: 'Saruman', spells:[frozenball] }, { name: 'Radagast', spells:[lightball] }]; let aggregation = [ { $match: {} }, // find all spells in the spells collection related to wizards and fill populate into wizards.spells { $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 { $sort: {'maxDamage' : -1} } ]; Spell.create(spells, (err, spells) => { if (err) throw(err); else { Wizard.create(wizards, (err, wizards) =>{ if (err) throw(err); else { Wizard.aggregate(aggregation) .exec((err, models) => { if (err) throw(err); else { console.log(models[0]); // eslint-disable-line console.log(models[1]); // eslint-disable-line console.log(models[2]); // eslint-disable-line Wizard.remove().exec(() => { Spell.remove().exec(() => { process.exit(0); }); }); } }); } }); } }); });