【问题标题】:How to get a nested group out of an aggregation如何从聚合中获取嵌套组
【发布时间】:2017-02-21 05:44:07
【问题描述】:

我的 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 创建额外查询的情况下使其正常工作?

【问题讨论】:

  • 对不起,当然!我要更新我的问题

标签: mongodb mongodb-query aggregation-framework


【解决方案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);
});

【讨论】:

  • 哇,太好了!这似乎有效。但我真的必须检查为什么 :-) 当你来自 MySQL(或一般的关系数据库)时,MongoDB 查询真的很混乱。
  • 管道算子的一些解释可以参考这个answer。懒得打字了,但概念都是一样的:)
  • 如果您需要进一步说明,请随时询问
  • 我浏览了代码并逐步运行查询。前两组很清楚,但$project 部分有点混乱。为什么我们需要将_id 设置为0fares 设置为1?非常感谢您的帮助!
  • $project管道中,可以选择/取消选择和重命名字段,类似于SQL中的SELECT fieldname AS newfieldname。设置_id: 0 会抑制_id 字段,即您将其从最终输出中排除。规范fare: 1 表示包含fares 字段,即来自上一个管道的字段包含在最终输出中。规范"arrivalAirport": "$_id", 重命名_id 字段,类似于SELECT _id AS arrivalAirport
猜你喜欢
  • 1970-01-01
  • 2020-11-11
  • 1970-01-01
  • 2017-07-26
  • 2019-10-06
  • 2017-07-16
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多