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

如何在Mongoose中查询嵌套文档里状态为active的订阅记录?

获取Mongoose嵌套文档中特定状态的订阅

嘿,看起来你已经搭好了Customer和Subscription的模型,现在想筛选出某个客户的active状态订阅对吧?我给你几个实用的方案,你可以根据场景选:

方案1:先查客户,再在代码里过滤(简单易上手)

如果你客户的订阅数量不多,直接先拿到完整的客户文档,然后用JS数组方法过滤就行,代码改动最小:

let customer = await CustomerModel.findOne({ telegram_id: ctx.chat.id });
// 过滤出status为active的订阅
const activeSubscriptions = customer.subscriptions.filter(sub => sub.status === 'active');
console.log(activeSubscriptions);

这种方法好处是不用写复杂的数据库查询,适合快速实现。

方案2:用MongoDB聚合管道在数据库层面过滤(高效,适合大数据量)

如果想让数据库直接返回过滤后的结果,减少数据传输,可以用聚合管道的$match和$project结合$filter操作符:

const result = await CustomerModel.aggregate([
  // 第一步:匹配到目标客户
  { $match: { telegram_id: ctx.chat.id } },
  // 第二步:投影出需要的字段,并用$filter过滤subscriptions
  {
    $project: {
      stripe_id: 1,
      email: 1,
      activeSubscriptions: {
        $filter: {
          input: "$subscriptions",
          as: "sub",
          cond: { $eq: ["$$sub.status", "active"] }
        }
      }
    }
  }
]);
// 聚合返回的是数组,取第一个元素
const activeSubscriptions = result[0]?.activeSubscriptions || [];

这种方法在数据库端完成过滤,性能更好,尤其是当订阅数量很多的时候。

方案3:用Mongoose查询的投影语法(简洁写法)

MongoDB 3.2及以上版本支持在投影里直接用$filter,你也可以把它写在findOne的投影参数里:

let customer = await CustomerModel.findOne(
  { telegram_id: ctx.chat.id },
  {
    stripe_id: 1,
    email: 1,
    activeSubscriptions: {
      $filter: {
        input: "$subscriptions",
        as: "sub",
        cond: { $eq: ["$$sub.status", "active"] }
      }
    }
  }
);
const activeSubscriptions = customer.activeSubscriptions || [];

这个写法和聚合管道效果类似,但更简洁,适合只需要单个文档的场景。

需要注意的是,$elemMatch虽然也能用来匹配嵌套文档,但它只会返回第一个符合条件的订阅,所以不适合你需要所有active订阅的需求,别用错啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:59:57