Reputation: 3358
I have a list of users to be displayed. I have 2 filters
1) Areas
2) Categories
I get proper filtered results when I apply only 1 filter i.e filter users based on selected categories or filter users based on areas.
Now I need to filter users based on both Categories and Areas selection. How should I approach to get the desired result?
Below is my working code to filter users based on selected categories:
User.find().populate('city').populate( {path: 'categories', match: { name: { $in: filterCatArray }}} ).populate('area').exec(function (err, users) {
users = users.filter(function(user) {
return user.categories; // return only filtered users
});
data = {fulldata:users};
res.render('home',{data:data});
});
User schema:
var userSchema = new Schema({
city: {type: mongoose.Schema.Types.ObjectId, ref: 'City',required: true},
area: {type: mongoose.Schema.Types.ObjectId, ref: 'Area', required: true},
categories: [{type: mongoose.Schema.Types.ObjectId, ref: 'Category', required: true}],
status: { type: Boolean, default: true },
created_at: Date,
updated_at: Date
});
Area Schema
var areaSchema = new Schema({
city: {type: mongoose.Schema.Types.ObjectId, ref: 'City'},
name: { type: String, required: true},
status: { type: Boolean, default: true },
created_at: Date,
updated_at: Date
});
Category Schema
var catSchema = new Schema({
name: { type: String, required: true},
status: { type: Boolean, default: true },
created_at: Date,
updated_at: Date
});
City Schema
var citySchema = new Schema({
name: { type: String, required: true},
status: { type: Boolean, default: true },
created_at: Date,
updated_at: Date
});
Upvotes: 1
Views: 2283
Reputation: 6766
I'm new to aggregation, but I recently started using it. I think populate
is great for simple cases, but when you want to start doing complex stuff such as filtering results based off other collections, you need to use aggregation.
This is untested but it would look roughly like this:
UserSchema.aggregate([
// 1 join city collection
{
$lookup: {
from: 'citys',
localField: 'city',
foreignField: '_id',
as: 'city'
}
},
{
$unwind: '$city'
},
// 2 join area collection
{
$lookup: {
from: 'areas',
localField: 'area',
foreignField: '_id',
as: 'area'
}
},
{
$unwind: '$area'
},
// 3 join categories collection
{
$unwind: '$categories'
},
{
$lookup: {
from: 'categories',
localField: 'categories',
foreignField: '_id',
as: 'category'
}
},
// 4 filter results that only have specified categories
{
$match: {
'category.name': { $in: filterCatArray },
'area.name': 'something' // just an example
}
},
// 5 group results by user
{
$group: {
_id: '$_id',
city: { $first: '$city' },
area: { $first: '$area' },
categories: { $push: '$category' },
status: { $first: '$status' },
created_at: { $first: '$created_at' },
updated_at: { $first: '$updated_at' },
}
}
], function (err, users) {
});
If there is a problem, comment each stage of the pipeline starting from the bottom to see what is happening.
For more information, read the following links:
Upvotes: 2