In my DB the ratingsAverage
's type is Number
. I want to implement filtering functionality depending on the ratings. For example, if the user selects 4, the result will be the ratings that fall within the range of 4 to 4.9. Selecting other ratings is possible too.
I'm struggling with the $or
operator, it doesn't return anything from the DB and I don't know the reason, I've tried a lot but no luck.
I have a function called destructSearchParams
which takes all the filter params, writes the query statement then passes the query into the API:
function destructSearchParams(searchParams) {
let sortBy;
if (searchParams.hasOwnProperty("sortBy")) {
sortBy = searchParams.sortBy;
delete searchParams.sortBy;
}
const filter = {};
for (const [key, value] of Object.entries(searchParams)) {
const valuesArray = value.split(',');
let query;
switch (key) {
case "roaster":
query = { $in: valuesArray};
break;
case "ratingsAverage":
const ratings = valuesArray.map(value => {
const minRating = Math.floor(Number(value));
const maxRating = minRating + 1;
return {ratingsAverage: { $gte: minRating, $lt: maxRating }};
});
query = {$or: ratings}
console.log(query);
break;
default:
query = { $regex: valuesArray.join('|')}; // Join with '|' to match any
break;
}
filter[key] = query;
}
return {filter, sortBy};
}
the implementation of case "ratingsAverage"
throws
CastError: Cast to number failed for value "[ { ratingsAverage: { '$gte': 4, '$lt': 5 } } ]" (type Array) at path "ratingsAverage"
stringValue: `"[ { ratingsAverage: { '$gte': 4, '$lt': 5 } } ]"`,
messageFormat: undefined,
kind: 'number',
value: [ { ratingsAverage: [Object] } ],
path: 'ratingsAverage',
reason: null,
valueType: 'Array'
After reading the MongoDB docs carefully again, I noticed that $or
operator doesn't have a field name before it, any field should be specified inside it, this is the correct format:
$or: [{ ratingsAverage: { $gte: 4, $lt: 5 } }, { ratingsAverage: {
$gte: 0, $lt: 3 } }]
The way I'm implementing the function is correct, my small problem was setting the key in this line of code after the switch-case
:
filter[key] = query;
In order to get around this, I've changed the const [key, value]
to let [key, value]
then, inside the case of ratingsAverage
the code became:
key = "$or";
query = ratings;