findOne() 返回所有值而不是一个

问题描述 投票:0回答:2

我正在使用 nodejs/express 和 mongoose 开发端点。端点应该只返回找到的 ID,如下所示:

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

但是,当我测试(localhost:3000 / api / one / 3000)时,它返回属于用户的所有值,而不是仅一个:

{
    "_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",
                }
]
        }
    ]
}

这是 mongo 模式:

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);

这是我认为 findOne() 上缺少的功能:

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);
  }
};

我该如何修复它,使其只返回给定的 id?

node.js mongodb mongoose mongodb-query
2个回答
0
投票

我认为根据您的文档设计,最好的方法是通过使用聚合并使用生成的对象来模拟

findOne
,如下所示:

export const getById = async (req, res) => {
   try {
      const id = req.params.id;
      const agg = await ScheduleModel.aggregate([
         {
            $match: {
               "schedule.events.id": id
            }
         },
         {
            $unwind: "$schedule"
         },
         {
             $unwind: "$schedule.events"
         },
         {
            $match: {
               "schedule.events.id": id
            }
         },
         {
            $replaceRoot: {
               newRoot: "$schedule.events"
            }
         }
      ]);
      const found = agg[0]; //< Use the 0 indexed object since aggregate returns an array.

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

请参阅此处了解聚合的工作示例。

注意:为了清楚起见,我使用

ScheduleModel
作为模型的名称来执行查询。将模型命名为
ScheduleSchema
可能会让将来使用此答案的初学者感到困惑。


0
投票

您可能喜欢这样的聚合功能:

db.collection.aggregate([
{
 "$match": {
  "schedule.events.id": 3000
 }
},
{
"$project": {
  "schedule": {
    "$map": {
      "input": "$schedule",
      "as": "s",
      "in": {
        "events": {
          "$filter": {
            "input": "$$s.events",
            "as": "e",
            "cond": {
              "$eq": [
                "$$e.id",
                3000
              ]
            }
          }
        }
      }
    }
   }
  }
 },
 {
 "$replaceRoot": {
   "newRoot": {
     $mergeObjects: "$schedule"
     }
    }
  },
  {
   "$replaceRoot": {
     "newRoot": {
      $mergeObjects: "$events"
    }
   }
  }
 ])

解释:

  1. 通过 id=3000 匹配嵌套对象
  2. 仅映射/过滤 id=3000 的匹配对象
  3. 用 2x ReplaceRoot 展平对象,这样你就得到了嵌套对象

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.