如何在Mongoose中按指定分类顺序对Product模型数据排序?
Got it, so you need to sort your Product documents in that specific custom category order: ['Clothes', 'Accessories', 'Footwears']? Regular Mongoose sort() won't cut it here because it only handles alphabetical or numerical ordering. Instead, we'll use MongoDB's aggregation framework to assign a custom priority value to each category, then sort by that value.
Here's the step-by-step solution:
- First, define your desired custom order array.
- Use the
$addFieldsstage to add a temporarysortPriorityfield, which uses$indexOfArrayto get the position of each document'sCategoryin your custom order. - Sort the results by this
sortPriorityfield. - Optional: Remove the temporary
sortPriorityfield with$projectif you don't want it in your final results.
Full Code Example:
const Product = require('./path/to/your/ProductModel'); // Define your desired category order const customCategoryOrder = ['Clothes', 'Accessories', 'Footwears']; Product.aggregate([ // Add a temporary priority field based on custom order { $addFields: { sortPriority: { $indexOfArray: [customCategoryOrder, '$Category'] } } }, // Sort by the priority (ascending = your custom order) { $sort: { sortPriority: 1 } }, // Optional: Remove the temporary sortPriority field from results { $project: { sortPriority: 0 } } ]) .then(sortedProducts => { console.log('Products sorted by custom category order:', sortedProducts); }) .catch(error => { console.error('Error sorting products:', error); });
Handling Categories Outside Your Custom List:
If you have products with categories not in your customCategoryOrder array, $indexOfArray will return -1, which will make them appear first in the results. If you want those to appear last instead, adjust the sortPriority logic with $cond to assign them a priority higher than your last custom category:
sortPriority: { $cond: { if: { $in: ['$Category', customCategoryOrder] }, then: { $indexOfArray: [customCategoryOrder, '$Category'] }, else: customCategoryOrder.length // Assigns a value higher than all custom indices } }
Bonus: Encapsulate as a Model Static Method
To make this reusable, add a static method directly to your Mongoose model so you can call it anywhere easily:
// In your Product model file const mongoose = require('mongoose') const { Schema } = mongoose const schema = new Schema({ Name: { type: String }, Category: { type: String }, Price: { type: Number } }) // Add custom sorting static method schema.statics.findSortedByCustomCategory = function() { const customOrder = ['Clothes', 'Accessories', 'Footwears']; return this.aggregate([ { $addFields: { sortPriority: { $cond: { if: { $in: ['$Category', customOrder] }, then: { $indexOfArray: [customOrder, '$Category'] }, else: customOrder.length } } } }, { $sort: { sortPriority: 1 } }, { $project: { sortPriority: 0 } } ]); }; module.exports = mongoose.model('Product', schema);
Now you can call it with just:
Product.findSortedByCustomCategory().then(sortedProducts => { // Use your sorted products });
内容的提问来源于stack exchange,提问作者Petr Vasilev




