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

Mongoose查询匹配courseID文档时仅返回materials数组符合moduleNo的项

问题描述

我需要查询匹配指定courseID的单个文档,要求返回结果中仅保留materials数组内moduleNo与传入参数匹配的对象。当前编写的查询虽然可以定位到正确的文档,但会返回materials数组的全部对象,需要对应的解决方案。

关联Schema定义
const materialSchema = new mongoose.Schema({
  courseID: String,
  materials: [
    {
      moduleNo: Number,
      moduleMaterial: String,
    },
  ],
});
当前实现代码
exports.getMaterials = (req, res) => {
  const { courseID, moduleNo } = req.query;
  Material.findOne(
    { courseID, "materials.moduleNo": moduleNo },
    (err, result) => {
      if (err) {
        console.error(err);
      } else {
        res.json(result);
      }
    }
  );
};
解决方案

原有逻辑的问题在于:查询条件里的"materials.moduleNo": moduleNo仅用于筛选符合要求的文档,不会对文档内嵌套数组的返回内容做过滤,所以会返回materials数组下的所有元素。

方法1:投影+$elemMatch(单匹配元素场景)

如果materials数组中每个moduleNo唯一,仅需要返回第一个匹配的数组元素,直接在findOne的第二个参数(投影配置)中,对materials字段使用$elemMatch指定匹配规则即可,修正后代码如下:

exports.getMaterials = (req, res) => {
  const { courseID, moduleNo } = req.query;
  // req.query拿到的参数默认是字符串,schema中moduleNo为数字类型,必须先做类型转换
  const targetModuleNo = Number(moduleNo);
  Material.findOne(
    { courseID },
    // 投影配置:指定返回字段,materials仅保留匹配moduleNo的元素
    { 
      courseID: 1,
      materials: { $elemMatch: { moduleNo: targetModuleNo } } 
    },
    (err, result) => {
      if (err) {
        console.error(err);
        return res.status(500).json({ msg: '查询失败' });
      }
      res.json(result);
    }
  );
};

方法2:聚合管道(多匹配元素/灵活过滤场景)

如果materials数组内可能存在多个moduleNo匹配的元素,需要返回所有符合条件的数组元素,使用聚合管道的$filter操作符实现:

exports.getMaterials = (req, res) => {
  const { courseID, moduleNo } = req.query;
  const targetModuleNo = Number(moduleNo);
  Material.aggregate([
    // 第一步:匹配对应courseID的文档
    { $match: { courseID } },
    // 第二步:过滤materials数组,保留所有符合条件的元素
    {
      $project: {
        courseID: 1,
        materials: {
          $filter: {
            input: "$materials",
            cond: { $eq: ["$$this.moduleNo", targetModuleNo] }
          }
        }
      }
    }
  ]).exec((err, results) => {
    if (err) {
      console.error(err);
      return res.status(500).json({ msg: '查询失败' });
    }
    // aggregate返回数组,取第一个元素即为匹配的单个文档
    res.json(results[0] || null);
  });
};

内容的提问来源于stack exchange,提问作者Jonan Mathew George

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:51:06