如何在Node.js中为Mongoose设置动态日期键
动态日期作为Mongoose属性名的实现方案
需求说明
需要将Mongoose Schema中的属性名设置为从今日开始的连续动态日期,生成数量为 workout_weeks * 7 个(比如workout_weeks=2时,生成14个连续日期),用户点击指定日期可快速获取对应训练内容。当前代码中所有属性都使用固定的当前日期,需调整为动态连续日期。
现有代码
用户Schema(userSchema)
// 使用moment库 let date = config.moment().format("YYYY-MM-DD"); const userSchema = new mongoose.Schema({ name: { type: String, }, age:{ type: Number, }, userStream :{ workout: [{ workout_weeks:{ type: Number, }, // 注释:按workout_weeks生成对应天数的训练记录,用二维数组存储 weeks: [ [ { [date]: { exercises: { type: [String], } } } ] ] }] } });
训练计划Schema(workoutSchema)
const workoutSchema = new mongoose.Schema({ workout_weeks:{ type: Number, }, [date]: { exercises: { type: String, } } });
用户注册接口(enroll)
export const enroll = async (req, res) => { try { const { id } = req.params; const { workout_id } = req.body; const user = await userSchema.findById(id); if (!user) { return res.status(400).json(errorResponse("User not found")); } const workout = await workout_id.findById(program_id) if (!workout) { return res.status(400).json(errorResponse("Workout not found")); } user.userStream.workout.push(program); await user.save(); return res .status(200) .json(sucessResponse("User enrolled successfully", user.userStream)); } catch (error) { res .status(500) .json(errorResponse(error?.message || "Something went wrong")); } };
解决方案
1. 调整Schema结构
Mongoose Schema为静态定义,无法在初始化时生成动态日期键,因此改用Mixed类型存储动态结构,同时优化数据结构以提升日期查询效率:
修改后的userSchema
const userSchema = new mongoose.Schema({ name: { type: String }, age: { type: Number }, userStream: { workout: [{ workout_weeks: { type: Number }, // 用对象存储,键为日期字符串,值为对应训练内容 dailyExercises: { type: mongoose.Schema.Types.Mixed, default: {} } }] } });
修改后的workoutSchema
const workoutSchema = new mongoose.Schema({ workout_weeks: { type: Number }, // 用Mixed类型存储动态日期的训练模板 dailyTemplates: { type: mongoose.Schema.Types.Mixed, default: {} } });
2. 修改enroll接口生成动态日期
在用户注册时,根据训练计划的workout_weeks生成从今日开始的连续日期,构建对应的训练结构:
export const enroll = async (req, res) => { try { const { id } = req.params; const { workout_id } = req.body; const user = await userSchema.findById(id); if (!user) { return res.status(400).json(errorResponse("用户不存在")); } // 修正原代码变量错误:使用workoutSchema查询训练计划 const workout = await workoutSchema.findById(workout_id); if (!workout) { return res.status(400).json(errorResponse("训练计划不存在")); } const totalDays = workout.workout_weeks * 7; const dailyExercises = {}; const today = config.moment(); // 生成连续日期并初始化训练内容 for (let i = 0; i < totalDays; i++) { const currentDate = today.clone().add(i, 'day').format("YYYY-MM-DD"); // 若训练计划有对应日期模板则复用,否则初始化空数组 dailyExercises[currentDate] = { exercises: workout.dailyTemplates[currentDate]?.exercises || [] }; } // 构建要添加的训练项 const newWorkoutEntry = { workout_weeks: workout.workout_weeks, dailyExercises }; user.userStream.workout.push(newWorkoutEntry); await user.save(); return res .status(200) .json(successResponse("用户注册成功", user.userStream)); } catch (error) { res .status(500) .json(errorResponse(error?.message || "服务器出错")); } };
3. 按日期查询训练内容示例
后续查询指定日期的训练内容时,可直接通过日期键访问:
// 查询2023-07-28的训练内容 const targetDate = "2023-07-28"; const workoutEntry = user.userStream.workout[0]; // 取第一个训练计划 const dayExercises = workoutEntry.dailyExercises[targetDate];
内容的提问来源于stack exchange,提问作者Shades
相关产品推荐
相关产品推荐

