You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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:

  • $lookup with 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.
  • $match with $size: 0: Filters out any quizzes where the user has already submitted a response (since userResponses would have at least one entry).
  • Final grouping: Converts the resulting list of quiz documents into a flat array of _id values, 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 11:52:40