Is there any way to have the equivalent of multiple groups of logical OR in Atlas Search? I have a query case where a result must satisfy at least one condition of one group of criteria and at least one condition of another group of criteria. Having two “should” clauses would not work. Also it is very limiting that there cannot be a $match before the $search stage. One of the groups of OR requires that a document field is in an array of ObjectIds, but we cannot use $equals in Atlas Search as it accepts only one ObjectId, not an array.
A user needs to be able to search for documents (books) that are in several shops by supplied array of shopIds (any of them should match) and also for books that fall in any one of the three categories (bestsellers, recommended - essentially 4 star or over rating, and new arrivals - essentially listed in the last 30 days) - the user may select one, two or all three categories and any should match (a book may be in all three). So both searches use logical OR. I can include a separate $match stage after $search, which seems the only option available given the constraints of Atlas Search. Is there any other way to do this in the $search stage?
search across books that fall in any one of the three categories (bestsellers, recommended - essentially 4 star or over rating, and new arrivals - essentially listed in the last 30 days)
The front-end supplies an array of shopIds. So my original solution was:
if (shopIds) {
for (let shopId of shopIds) {
searchStage.$search.compound.should.push(
{
equals: {
path: "shopInfo.shopId",
value: ObjectId(shopId)
}
}
)
}
searchStage.$search.compound.minimumShouldMatch = 1;
}
I am not sure how I can do it with filter for arrays of values (any should match)? The problem seems to me is that “equals” does not accept an array of values (similar to $in).
For categories, I have used “exists” + “range”.
if (category && category !== 'all') {
if (category === "bestsellers") {
searchStage.$search.compound.filter.push({
exists: {
path: "bestseller"
}
});
} else if (category === "recommended") {
searchStage.$search.compound.filter.push({
exists: {
path: "recommended"
}
});
} else if (category === "new arrivals") {
// new arrivals - 30 days before todays date; use 31 to account for time
afterDate.setDate(todaysDate.getDate() - 31);
searchStage.$search.compound.filter.push({
range: {
path: "dateListedForSale",
gt: afterDate
}
});
}
}
But now I need to use “should” too because I need mutiple select of several categories at the same time.