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

Mongoose中按用户名及日期范围查询数组内Exercise对象

解决Mongoose中按用户名查询并过滤子数组日期范围的问题

我来帮你搞定这个问题!首先得明确你之前的错误出在哪:你把日期范围的查询条件错误地放到了find方法的投影参数(第二个参数)里,还错误拆分了查询条件为多个参数,这才触发了Unsupported projection option的报错——MongoDB的投影参数不支持$gte/$lte这类查询操作符。

错误原因拆解

你之前的find调用格式完全不符合规范:

// 错误写法:把查询条件拆成多个参数,还将$gte/$lte错误放在投影逻辑里
Exerciser.find( { "username": name }, { "exercises.date": { "$gte": from }}, { "exercises.date": { "$lte": to }} )

find的正确参数顺序是:(查询条件, 投影规则, 选项配置),所有匹配文档的逻辑都应该放在第一个参数里;而如果要过滤子数组的元素,需要用投影里的数组操作符或者聚合管道来实现。

最简解决方案:用$filter投影筛选子数组

如果你只想返回指定用户的文档,且只保留exercises中日期在from到to之间的条目,用$filter投影是最直接的方案(MongoDB 3.2+支持,Mongoose完全兼容):

let user = await Exerciser.find(
  { username: name }, // 第一步:匹配目标用户名
  {
    username: 1, // 保留username字段
    exercises: {
      $filter: {
        input: "$exercises", // 要筛选的目标数组
        as: "exercise", // 数组元素的别名
        cond: {
          $and: [
            { $gte: ["$$exercise.date", new Date(from)] }, // 日期大于等于起始值
            { $lte: ["$$exercise.date", new Date(to)] }   // 日期小于等于结束值
          ]
        }
      }
    }
  }
).exec((err, data) => {
  if (err) {
    res.json({ Error: "Data not found" });
    return done(err);
  } else {
    res.json(data);
    return done(null, data);
  }
});

额外优化:修正Schema的日期默认值

你的Schema里date的默认值写法有个小坑:default: new Date()会在Schema定义的瞬间生成一个固定日期,而不是每次创建文档时取当前时间。改成Date.now才是正确的写法:

let ExerciserSchema = new Schema({
  username: { type: String, required: true },
  exercises: [{
    desc: String,
    duration: Number,
    date: { type: Date, default: Date.now } // 每次创建文档时自动生成当前时间
  }]
});

关于日期格式的说明

你看到错误里的毫秒数是MongoDB存储Date对象的内部格式,完全不用在意——只要你查询时传入的是合法的Date对象(比如new Date("2018-05-01T00:00:00.000Z")),MongoDB会自动完成格式匹配,和你console.log看到的ISO格式没有冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:08:14