如何从聚合中获取嵌套组

时间:2017-02-20 21:21:47

标签: mongodb mongodb-query aggregation-framework

我的Mongo数据库中有以下架构:

[
  {
    departureAirport: "JFK",
    arrivalAirport: "FRA",
    departureDate: "2017-02-22T04:00:00.000Z",
    arrivalDate: "2017-02-22T09:45:00.000Z",
    flightNumber: "FOOBAR",
    availableSeats: 9,
    cheapestFare: 65.99
  }
]

此数据库中有几千行,包括不同的出发机场,到达机场和日期。

现在我想将结果分组,以获得每个到达机场每月最便宜的价格:

[
  {
    arrivalAirport: "FRA",
    fares: [
     {'2017-02': 65.99},
     {'2017-03': 65.99}
    ]
  },
  {
    arrivalAirport: "JFK",
    fares: [
     {'2017-02': 65.99},
     {'2017-03': 65.99}
    ]
  }
]

甚至更好:

[
  {
    arrivalAirport: "FRA",
    fares: {
     '2017-02': 65.99,
     '2017-03': 65.99
    }
  },
  {
    arrivalAirport: "JFK",
    fares: {
     '2017-02': 65.99,
     '2017-03': 65.99
    }
  }
]

这是我尝试的方式:

  Flight.aggregate([
    {
      $match: filter
    },
    {
      $group: {
        _id: {
          arrival: '$arrivalAirport'
        }
      }
    },
    {
      $group: {
        _id: {
          year: { $year: '$departureDate' },
          month: { $month: '$departureDate' }
        },
        cheapestFare: { $min: '$cheapestFare' }
      }
    },
    {
      $sort: {
        departureDate: 1
      }
    }
  ]

显然这不起作用,因为我需要所有可用的月份及每个arrivalAirport的票价而不是每个arrivalAirport一个组。

接下来我一直在寻找:子查询(我来自SQL,所以Mongo对我来说相当新)。但似乎MongoDB不支持像子查询这样的东西(所以我可以为每个arrivalAirport创建一个子查询)。是否还有其他选项可以在不为每个arrivalAirport创建额外查询的情况下使其生效?

1 个答案:

答案 0 :(得分:1)

您可以尝试运行以下聚合管道:

Flight.aggregate([
    {
        "$group": {
            "_id": {
                "arrivalAirport": "$arrivalAirport",
                "month": { "$dateToString": { "format": "%Y-%m", "date": "$arrivalDate" } }
            },
            "cheapestFare": { "$min": "$cheapestFare" }
        }
    },
    {
        "$group": {
            "_id": "$_id.arrivalAirport",
            "fares": {
                "$push": {
                    "date": "$_id.month",
                    "fare": "$cheapestFare"
                }
            }
        }       
    },
    {
        "$project": {
            "_id": 0,
            "arrivalAirport": "$_id",
            "fares": 1
        }
    }
], function(err, results) {
    if (err) throw err;
    console.log(results);
});