Reputation: 789
I need to retrieve from a collection of random docs based on a limit given. If some filters are provided they should be added to filter the results of the response. I'm able to build the match and size based on the fields provided but even tho I have 20 documents that meet the filter when I make the call I receive only 2 or 3 docs back and I can't seem to figure it out. If I set only the limit it does give me back N random docs based on the limit but if I add a filter it won't give me the wanted results.
This is what I do now
const limit = Number(req.query.limit || 1);
const difficulty = req.query.difficulty;
const category = req.query.category;
const settings = [
{
$sample: {
size: limit
}
}
];
if (difficulty && category) {
settings.push({
$match: {
difficulty: difficulty,
category: category
}
});
} else if (difficulty && category == null) {
settings.push({
$match: {
difficulty
}
});
}
if (difficulty == null && category) {
settings.push({
$match: {
category
}
});
}
console.log(settings);
Question.aggregate(settings)
.then(docs => {
const response = {
count: docs.length,
difficulty: difficulty ? difficulty : "random",
questions:
docs.length > 0
? docs.map(question => {
return {
_id: question._id,
question: question.question,
answers: question.answers,
difficulty: question.difficulty,
category: question.category,
request: {
type: "GET",
url:
req.protocol +
"://" +
req.get("host") +
"/questions/" +
question._id
}
};
})
: {
message: "No results found"
}
};
res.status(200).json(response);
})
.catch(err => {
res.status(500).json({
error: err
});
});
Upvotes: 1
Views: 178
Reputation: 46461
Order of the stages matters here. You are pushing the $match
stage after the $sample
stage which first put the $size
to whole the documents and then applies the $match
stage on the $sample
d
documents documents.
So finally you need to push the $sample
stage after the $match
stage. The order should be
const limit = Number(req.query.limit || 1);
const difficulty = req.query.difficulty;
const category = req.query.category;
const settings = []
if (difficulty && category) {
settings.push({
$match: {
difficulty: difficulty,
category: category
}
})
} else if (difficulty && category == null) {
settings.push({
$match: {
difficulty
}
})
}
if (difficulty == null && category) {
settings.push({
$match: {
category
}
})
}
setting.push({
$sample: {
size: limit
}
})
console.log(settings);
Question.aggregate(settings)
Upvotes: 1