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

如何用Mongoose在MongoDB中按条件筛选数组内关联文档

问题:筛选符合状态、日期条件的用户通知

需求

仅获取符合req.query中指定状态、from_date和to_date条件的用户通知。

数据模型

User Schema

const userSchema = mongoose.Schema({
  email: {
    type: String,
    required: true
  },
  password: {
    type: String,
    minlength: 8,
    required: true
  },
  notifications: [{
    notification: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "Notification"
    },
    status: {
      type: String,
      enum: ["Not Acknowledged", "Acknowledged"],
      default: "Not Acknowledged"
    },
  }]
})

Notification Schema

const notificationSchema = mongoose.Schema({
  description: { type: String },
  remind_on: { type: Date },
  remind_at: { type: Date },
});

问题重现

尝试以下代码后,返回的是用户的全部通知,没有按条件筛选:

const statusQuery = {};
if(status) {
  statusQuery.match = { 'notifications.status': status }
}
const searchNotifications = await User.findById(user._id)
  .populate({
    path: "notifications",
    ...statusQuery,
    populate: {
      path: "notification",
      populate: [
        { path: "assignee", select: "first_name last_name" },
        { path: "case", select: "case_id" },
      ],
    },
  })
  .select("notifications");

代码逻辑:通过用户ID查询文档后,在populate阶段添加筛选条件。

问题原因

  1. populate筛选notifications数组时,match的路径写错了——当前上下文是数组中的单个子文档,不需要写'notifications.status',直接用status即可。
  2. 没有添加日期范围的筛选逻辑,无法过滤from_date和to_date对应的通知。

修复后的代码

// 初始化用户通知子文档的筛选条件
const notificationFilter = {};
// 处理状态筛选
if (status) {
  notificationFilter.status = status;
}

// 初始化关联Notification文档的日期筛选条件
const nestedNotificationFilter = {};
// 处理起始日期(这里以remind_on为例,可根据需求换成remind_at)
if (from_date) {
  nestedNotificationFilter.remind_on = { ...nestedNotificationFilter.remind_on, $gte: new Date(from_date) };
}
// 处理结束日期
if (to_date) {
  nestedNotificationFilter.remind_on = { ...nestedNotificationFilter.remind_on, $lte: new Date(to_date) };
}

const searchNotifications = await User.findById(user._id)
  .populate({
    path: "notifications",
    // 筛选用户通知子文档的状态
    match: notificationFilter,
    populate: {
      path: "notification",
      // 筛选关联通知的日期范围
      match: nestedNotificationFilter,
      populate: [
        { path: "assignee", select: "first_name last_name" },
        { path: "case", select: "case_id" },
      ],
    },
  })
  .select("notifications");

关键说明

  • 筛选用户的notifications数组元素时,match直接使用子文档的字段名(比如status),因为此时MongoDB正在遍历数组中的每个子文档进行匹配。
  • 日期筛选需要针对关联的Notification文档,在内部的populate中添加match条件,注意要将传入的日期字符串转为Date类型,确保MongoDB能正确处理范围查询。
  • 如果需要用remind_at作为日期筛选字段,直接替换代码中的remind_on即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:47:23