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

Node.js/Express+Mongoose接口findOne返回全部数据的修复

问题:如何通过Node.js/Express + Mongoose返回指定ID的单条事件数据

预期返回格式

请求localhost:3000/api/one/3000时,预期仅返回指定ID的单条事件:

{
    "id": 3000,
    "group": 3,
    "title": "",
    "start_time": "2023-07-31T11:00:00.000Z",
    "end_time": "2023-07-31T20:00:00.000Z",
    "category": "green"
}

实际返回格式

实际接口返回了用户名下的所有事件数据:

{
    "_id": "658",
    "schedule": [
        {
            "events": [
                {
                    "id": 3000,
                    "group": 3,
                    "title": "",
                    "start_time": "2023-12-01T11:00:00.000Z",
                    "end_time": "2023-12-01T20:00:00.000Z",
                    "category": "green"
                },
                {
                    "id": 3001,
                    "group": 3,
                    "title": "",
                    "start_time": "2023-12-02T11:00:00.000Z",
                    "end_time": "2023-12-02T20:00:00.000Z",
                    "category": "green"
                },
                {
                    "id": 3002,
                    "group": 3,
                    "title": "",
                    "start_time": "2023-12-03T11:00:00.000Z",
                    "end_time": "2023-12-03T20:00:00.000Z",
                    "category": "green"
                },
                {
                    "id": 3003,
                    "group": 3,
                    "title": "",
                    "start_time": "2023-12-04T11:00:00.000Z",
                    "end_time": "2023-12-04T20:00:00.000Z",
                    "category": "green"
                },
                {
                    "id": 3004,
                    "group": 3,
                    "title": "",
                    "start_time": "2023-12-07T11:00:00.000Z",
                    "end_time": "2023-12-07T20:00:00.000Z",
                    "category": "green"
                }
            ]
        }
    ]
}

MongoDB Schema定义

import mongoose, { model, Schema } from "mongoose";

const eventSchema = new mongoose.Schema({
  id: Number,
  group: Number,
  title: String,
  start_time: Date,
  end_time: Date,
  category: String,
});

const individualSchema = new mongoose.Schema({
  name: String,
  events: [eventSchema],
});

const ScheduleSchema = new mongoose.Schema({
  schedule: [individualSchema],
});

export default model("Schedule", ScheduleSchema);

当前查询函数

export const getById = async (req, res) => {
  try {
    const id = req.params.id;
    const found = await ScheduleSchema.findOne(
      { "schedule.events.id": id },
      { "schedule.events.$": 1 }
    );

    res.json(found);
  } catch (error) {
    console.log(error);
    console.error(error);
  }
};

解决方案

问题根源

当前findOne结合位置运算符$仅能匹配第一层嵌套数组(schedule)的第一个匹配项,无法深入第二层数组(events)提取单个事件,因此返回的仍是包含所有事件的嵌套结构。另外,req.params.id是字符串类型,与Schema中id的Number类型不匹配,会导致精准匹配失效。

方案1:使用聚合管道(推荐,数据库层面完成过滤)

通过MongoDB聚合管道逐层解开嵌套数组,匹配目标事件后直接返回单条数据:

export const getById = async (req, res) => {
  try {
    const eventId = parseInt(req.params.id); // 转换为数字类型匹配Schema定义
    const result = await ScheduleSchema.aggregate([
      // 解开schedule数组,将每个元素拆分为独立文档
      { $unwind: "$schedule" },
      // 解开events数组,将每个事件拆分为独立文档
      { $unwind: "$schedule.events" },
      // 匹配指定ID的事件
      { $match: { "schedule.events.id": eventId } },
      // 将事件数据作为根文档返回,去除外层嵌套
      { $replaceRoot: { newRoot: "$schedule.events" } }
    ]);

    if (result.length > 0) {
      res.json(result[0]);
    } else {
      res.status(404).json({ message: "Event not found" });
    }
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Server error" });
  }
};

方案2:查询后手动提取事件(代码层面处理)

若不想使用聚合,可在查询到完整数据后,通过遍历嵌套数组筛选目标事件:

export const getById = async (req, res) => {
  try {
    const eventId = parseInt(req.params.id);
    const found = await ScheduleSchema.findOne(
      { "schedule.events.id": eventId }
    );

    if (!found) {
      return res.status(404).json({ message: "Event not found" });
    }

    // 遍历嵌套结构找到目标事件
    let targetEvent = null;
    for (const individual of found.schedule) {
      targetEvent = individual.events.find(event => event.id === eventId);
      if (targetEvent) break;
    }

    targetEvent 
      ? res.json(targetEvent) 
      : res.status(404).json({ message: "Event not found" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Server error" });
  }
};

内容的提问来源于stack exchange,提问作者Felipe Useda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:53:15