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

使用Mongoose访问Schema.Types.ObjectId关联值:按训练名查运动标题

嘿,我来帮你搞定这个查询需求!根据你描述的训练管理应用场景,核心是利用Mongoose的populate()方法来关联查询Workout和它关联的Exercise数据,下面一步步给你理清楚实现方式:

1. 先确认模型的正确定义

首先得保证你的两个模型引用关系配置正确,这是关联查询的基础:

Exercise模型(exercise.js)

需要包含你要查询的title字段,示例如下:

const mongoose = require('mongoose');

const exerciseSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true // 运动标题必填,比如“俯卧撑”
  },
  // 你可以按需添加其他字段,比如组数、次数、时长等
});

module.exports = mongoose.model('Exercise', exerciseSchema);

Workout模型(workout.js)

exercises字段要定义为Exercise模型的ObjectId数组,通过ref指定关联的模型名称:

const mongoose = require('mongoose');

const workoutSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true // 训练名称,比如“上肢训练”
  },
  creatorEmail: {
    type: String,
    required: true // 创建者邮箱
  },
  exercises: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Exercise' // 这里必须和Exercise模型导出的名称一致
  }]
});

module.exports = mongoose.model('Workout', workoutSchema);
2. 控制器实现按训练名称查询并关联运动标题

在Workout控制器里,我们用findOne()(或find()如果允许多个同名训练)配合populate(),只取出我们需要的Exercise标题:

const Workout = require('../models/workout');

// 按训练名称查询关联的运动标题
exports.getWorkoutWithExercises = async (req, res) => {
  try {
    // 从请求参数中获取训练名称,比如请求地址是 /workouts?name=上肢训练
    const targetWorkoutName = req.query.name;

    // 查询指定名称的训练,并关联查询exercises的title字段
    // `-_id`表示不返回Exercise的_id,按需选择是否保留
    const workout = await Workout.findOne({ name: targetWorkoutName })
      .populate('exercises', 'title -_id');

    if (!workout) {
      return res.status(404).json({ message: '未找到对应的训练记录' });
    }

    // 整理返回结果,只返回需要的信息
    const responseData = {
      workoutName: workout.name,
      creator: workout.creatorEmail,
      exercises: workout.exercises // 这里已经是只包含title的数组了
    };

    res.status(200).json(responseData);
  } catch (error) {
    res.status(500).json({ message: '查询失败', error: error.message });
  }
};

如果需要支持模糊查询(比如输入“上肢”就能匹配“上肢训练”),可以把查询条件改成正则:

const workout = await Workout.findOne({ 
  name: { $regex: targetWorkoutName, $options: 'i' } // 'i'表示忽略大小写
})
.populate('exercises', 'title -_id');
3. 配置路由(routes.js)

把这个查询接口挂载到路由上:

const express = require('express');
const router = express.Router();
const workoutController = require('../controllers/workout');

// GET请求:通过训练名称查询关联运动
router.get('/workouts', workoutController.getWorkoutWithExercises);

module.exports = router;
额外注意点
  • 确保你在创建Workout的时候,已经正确将Exercise的ObjectId存入了exercises数组,否则populate()会返回空数组。
  • 如果需要返回Exercise的更多字段,比如title和sets(组数),可以把populate的第二个参数改成'title sets'。

内容的提问来源于stack exchange,提问作者Darran Blackweir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:13:29