Mangusta, ordina la query per campo popolato

Per quanto ne so, è ansible ordinare i documenti popolati con Mongoose ( fonte ).

Sto cercando un modo per ordinare una query da uno o più campi popolati.

Considera questi due schemi Mongoose:

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

Esempio JSON:

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

Vorrei ordinare quei maghi per i loro danni agli incantesimi, usando qualcosa come:

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

In realtà sto facendo questo genere di cose dopo aver interrogato e vorrei ottimizzarlo.

Chiediti (e qui ci sono le risposte):

Quello che voglio? Ordina i maghi per il loro danno da incantesimo (dovrebbe essere un campo aggiuntivo, probabilmente la sum del danno degli incantesimi.

Quello che ho fatto: ho ordinato gli INCANTESIMI del mago.

Cosa dovresti fare: Wizard.find ({}). Sort ({power: ‘asc’}) e poi popola con gli incantesimi e fai quello che vuoi. Il potere è un altro campo in Wizard. Ne avrai bisogno perché, anche se popoli i tuoi incantesimi, avrai una serie di incantesimi e non ti aiuterà.

Spero che questo ti aiuti.

È ansible specificare implicitamente solo i parametri richiesti del metodo populate:

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

Dai un’occhiata a http://mongoosejs.com/docs/api.html#document_Document-populate Ecco un esempio da un link sopra.

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

Anche se questo è piuttosto un vecchio post, mi piacerebbe condividere una soluzione attraverso la pipeline di ricerca di aggregazione MongoDB

La parte importante è questa:

  { $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} } 

Trova sotto un esempio completo

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

ecco l’esempio di mongoose doc.

 var PersonSchema = new Schema({ name: String, band: String }); var BandSchema = new Schema({ name: String }); BandSchema.virtual('members', { ref: 'Person', // The model to use localField: 'name', // Find people where `localField` foreignField: 'band', // is equal to `foreignField` // If `justOne` is true, 'members' will be a single doc as opposed to // an array. `justOne` is false by default. justOne: false, options: { sort: { name: -1 }, limit: 5 } });