How to filter products by deep nested populated fields. catalogProduct is an ObjectId (ref to catalog product). category is an ObjectId inside catalogProduct (ref to categories). Categories is an array of category ids.
products = await StorageModel
.find({"catalogProduct.category": {$in: categories }})
.skip((page-1)*8)
.limit(8)
.populate({path: "catalogProduct", populate: {path: "category", select: "name"}})
.select('-__v')
.sort({_id: -1});
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You'll need to do a $lookup
on the catelogProduct collection so that you can access the catelogProduct data in the query.
Unfortunately that's only available when using Mongo Aggregation, however aggregation is very powerful and is perfect for this sort of thing. You could do something like this:
const products = await StorageModel.aggregate([
{ $lookup: { // Replace the Catelog Product ID with the Catelog Product
from: "catelogProduct",
localField: "catelogProduct",
foreignField: "_id",
as: "catelogProduct"
} },
{ $lookup: { // Replace the Category ID with the Category
from: "categories",
localField: "catelogProduct.category",
foreignField: "_id",
as: "catelogProduct.category"
} },
{ $addFields: { // Replace the Category with its name
"catelogProduct.category": "$catelogProduct.category.name"
} },
{ $match: {
"catalogProduct.category": { $in: categories }
} },
{ $sort: { _id: -1 } },
{ $skip: (page - 1) * 8 },
{ $limit: 8 }
]);
Ideally you wouldn't do the $lookup
until you've paginated the results (using $skip
and $limit
), but in this case it makes sense to do the $lookup
first. Make sure you've got an index on catelogProduct._id
and categories._id
to optimize the query.
For more info on $lookup
, look at this article. For more info on Mongo Aggregation, look at this article.