如何使用Mongoose聚合替代For循环实现跨集合数据筛选
Refactoring to Mongoose Aggregation for Unsubmitted Quizzes
Hey there! Let's replace that loop with a single Mongoose aggregation pipeline—this will be much more efficient because it cuts down on database round-trips (no more N+1 queries!). Here's how to replicate your exact logic in one query:
const filteredQuizIds = await Quiz.aggregate([ // Step 1: Link each Quiz to the current user's Response records for it { $lookup: { from: 'responses', // Make sure this matches your Response collection's name (usually lowercase plural) localField: '_id', foreignField: 'quizID', let: { currentUserId: userID }, // Pass the userID into the sub-pipeline pipeline: [ // Only fetch responses from the current user for this quiz { $match: { $expr: { $eq: ['$userID', '$$currentUserId'] } } } ], as: 'userResponses' // Stores matching responses in this array field } }, // Step 2: Keep only Quizzes where the user has no responses { $match: { userResponses: { $size: 0 } } }, // Step 3: Keep only the _id field (we don't need other quiz data) { $project: { _id: 1 } }, // Step 4: Convert the list of { _id: ... } docs into a single array of ids { $group: { _id: null, ids: { $push: '$_id' } } }, // Step 5: Clean up the output to just the ids array { $project: { _id: 0, ids: 1 } } ]); // Extract the final array (handle case where no unsubmitted quizzes exist) const filtered = filteredQuizIds.length > 0 ? filteredQuizIds[0].ids : []; console.log(filtered);
How this works:
$lookupwith sub-pipeline: Instead of querying Responses in a loop, we join the Quiz and Response collections directly in the database. The sub-pipeline ensures we only pull in responses from the specific user you're checking.$matchwith$size: 0: Filters out any quizzes where the user has already submitted a response (sinceuserResponseswould have at least one entry).- Final grouping: Converts the resulting list of quiz documents into a flat array of
_idvalues, matching the exact output of your original loop.
Why this is better:
Your original code makes 1 + N database calls (1 to fetch all quizzes, N to check each one's responses). This aggregation does it in 1 call total, which is way faster as your Quiz collection grows.
内容的提问来源于stack exchange,提问作者Vinita
相关产品推荐
相关产品推荐

