查询数组中的嵌入对象

时间:2018-05-18 17:17:50

标签: mongodb mongoose aggregation-framework

我正在为页面制作过滤系统。我有以下架构结构:

User: {
  firstName
  lastName
  email
  subscriptions: [
    {
      id: '5a687c7680eab407064c3990'
      plan: "TRIAL"
      startDate: '2018-03-01'
      endDate: '2018-04-01'
      status: 'EXPIRED'
    }
    {
      id: '5afacc040e53b4075dcdd600'
      plan: "BASIC"
      startDate: '2018-04-01'
      endDate: '2018-05-01'
      status: 'EXPIRED'
    }
    {
      id: '5afacc040e53b4075dcdd600'
      plan: "BASIC"
      startDate: '2018-05-01'
      endDate: '2018-06-01'
      status: 'CANCELLED'
    }
  ]
}

我需要获得一个包含以下内容的用户列表:

  • firstName,lastName或email是'john'
  • 当前订阅状态:EXPIRED
  • 当前订阅计划:TRIAL

这应该返回null。

这是我试过的:

User.find({
  $or:
    [
      { firstName: { $regex: args.search, $options: 'i' } },
      { lastName: { $regex: args.search, $options: 'i' } },
      { email: { $regex: args.search, $options: 'i' } },
    ],
  $and:
    [
      { 'subscriptions.status': 'EXPIRED' },
      { 'subscriptions.plan': 'TRIAL' },
    ],
}).limit(limit).skip(skip);

问题是我只需要搜索用户的最新订阅(具有最新startDate的订阅),而不是数组中的每个对象。有没有办法做到这一点?我在架构上也有一个虚拟字段,但似乎你无法查询虚拟字段。

1 个答案:

答案 0 :(得分:0)

您应该尝试使用聚合查询来执行此操作...

首先你必须

  1. $match firstName,lastName,email
  2. 然后$unwind根据startDate
  3. 对订阅进行排序
  4. 然后再次$match获取计划和状态

    db.collection.aggregate([
      {
        $match: {
          $or: [
            {
              firstName: {
                $regex: args.search,
                $options: "i"
              }
            },
            {
              lastName: {
                $regex: args.search,
                $options: "i"
              }
            },
            {
              email: {
                $regex: args.search,
                $options: "i"
              }
            }
          ]
        }
      },
      {
        $unwind: "$subscriptions"
      },
      {
        $sort: {
          "subscriptions.startDate": -1
        }
      },
      {
        $group: {
          _id: "$_id",
          subscriptions: {
            "$first": "$subscriptions"
          }
        }
      },
      {
        $match: {
          "subscriptions.status": "EXPIRED",
          "subscriptions.plan": "TRIAL"
        }
      },
    
    ])