MongoDB聚合多个分组查询

3

我有一个名为test的mongodb集合,数据长这样 -

{ 
    "_id" : ObjectId("5dd271d30c90441941eb92b1"), 
    "h_id" : NumberInt(1), 
    "ota" : NumberInt(1), 
    "search_date" : ISODate("2019-09-09T00:00:00.000+0000"), 
    "data" : [{
        "price" : NumberInt(12500), 
        "code" : "02246933", 
    }
    {
        "price" : NumberInt(11500), 
        "code" : "02246934", 
    }
    {
        "price" : NumberInt(13500), 
        "code" : "02246935", 
    }
    {
        "price" : NumberInt(14500), 
        "code" : "02246936", 
    }]
}
{ 
    "_id" : ObjectId("5dd271d30c90441941eb92b2"), 
    "h_id" : NumberInt(1), 
    "ota" : NumberInt(1), 
    "search_date" : ISODate("2019-09-10T00:00:00.000+0000"), 
    "data" : [{
        "price" : NumberInt(2500), 
        "code" : "102246933", 
    }
    {
        "price" : NumberInt(1500), 
        "code" : "102246934", 
    }
    {
        "price" : NumberInt(3500), 
        "code" : "102246935", 
    }
    {
        "price" : NumberInt(4500), 
        "code" : "102246936", 
    }]
}

我想写一个查询,它能够给出像这样的结果 -
{ 
    "h_id" : NumberInt(1), 
    "ota_group": [{
    "ota": NumberInt(1),
    "search_date_group": [{
        "search_date": ISODate("2019-09-09T00:00:00.000+0000"),
        "min_price": NumberInt(11500),
        "min_code": "02246934",
        "max_price": NumberInt(14500),
        "max_code": "02246936"
        },
        {
        "search_date": ISODate("2019-09-10T00:00:00.000+0000"),
        "min_price": NumberInt(1500),
        "min_code": "102246934",
        "max_price": NumberInt(4500),
        "max_code": "102246936"
        }]
    }]
}
{ 
    "h_id" : NumberInt(2), 
    "ota_group": [{
    "ota": NumberInt(1),
    "search_date_group": [{
        "search_date": ISODate("2019-09-09T00:00:00.000+0000"),
        "min_price": NumberInt(11500),
        "min_code": "02246934",
        "max_price": NumberInt(14500),
        "max_code": "02246936"
        },
        {
        "search_date": ISODate("2019-09-10T00:00:00.000+0000"),
        "min_price": NumberInt(1500),
        "min_code": "102246934",
        "max_price": NumberInt(4500),
        "max_code": "102246936"
        }]
    }]
}

目标: 我想使用 h_id 对文档进行分组,然后再使用 ota 对每个子组进行分组。进一步地,这些子子组应该使用 search_date 进行分组。对于每个 search_date,我需要 max_price、max_code 和 min_price、min_code。

据我理解,我需要执行多个(嵌套)group by 才能实现这个结果。

我是 Mongodb 的新用户,尝试编写查询语句:

db.test.aggregate(
[  
    {
        "$match": {
          'h_id': 1
    },
    { "$unwind": "$data" },
    { "$group": 
        {
            '_id': '$_id',
            'h_id': { $first: "$h_id" },
            'ota': { $first: "$ota" },
            'search_date': { $first: "$search_date" },
            'min_price': {
                '$min': "$data.price",
            },
            'min_price': {
                '$min': "$data.price"
            },
            'max_price': {
                '$max': "$data.price"
            },
            'max_price': {
                '$max': "$data.price"
            }
        }
    },
     { "$group": 
        {
            '_id': {h_id: "$h_id"},            
            'info': { $push:  { 'search_date': "$search_date", 'ota': "$ota", 'min_price': "$min_price", 'max_price': "$max_price", 'min_price': "$min_price", 'max_price': "$max_price" } }
        }
    },
    { "$group": 
        {
            '_id': "$_id.h_id",            
            'info': { $first: "$info" },
        }
    },
]);  

但这远远不够满足需求。 有人能给出一些提示/想法如何实现吗?


我想编写一个查询,可以给出类似于结果的东西 - 好的。但情景是什么?你想在这里如何分组? - Ashh
@Ashh:抱歉问题不完整,我已经编辑过了,请看一下。 - DEV
1个回答

1

有趣的问题,幸运的是至少有一个答案。

诀窍是双重的:

  • 使用$sort阶段,后跟$first和$last累加器,而不是$min和$max。
  • 从更精确的分组阶段开始,然后进行“取消分组”。

这是您需要的查询:

db.collection.aggregate([
  {
    $unwind: "$data"
  },
  {
    $sort: {
      "data.price": 1
    }
  },
  {
    $group: {
      _id: {
        h_id: "$h_id",
        ota: "$ota",
        search_date: "$search_date"
      },
      "min_price": {
        $first: "$data.price"
      },
      "min_code": {
        $first: "$data.code"
      },
      "max_price": {
        $last: "$data.price"
      },
      "max_code": {
        $last: "$data.code"
      },

    }
  },
  {
    $group: {
      _id: {
        h_id: "$_id.h_id",
        ota: "$_id.ota",

      },
      search_date_group: {
        $push: {
          "search_date": "$_id.search_date",
          "max_code": "$max_code",
          "max_price": "$max_price",
          "min_code": "$min_code",
          "min_price": "$min_price",

        }
      }
    }
  },
  {
    $group: {
      _id: {
        h_id: "$_id.h_id",

      },
      "ota_group": {
        $push: {
          ota: "$_id.ota",
          search_date_group: "$search_date_group"
        }
      }
    }
  }
])

它将精确输出您所需的内容:

 {
    "_id": {
      "h_id": 1
    },
    "ota_group": [
      {
        "ota": 1,
        "search_date_group": [
          {
            "max_code": "02246936",
            "max_price": 14500,
            "min_code": "02246934",
            "min_price": 11500,
            "search_date": ISODate("2019-09-09T00:00:00Z")
          },
          {
            "max_code": "102246936",
            "max_price": 4500,
            "min_code": "102246934",
            "min_price": 1500,
            "search_date": ISODate("2019-09-10T00:00:00Z")
          }
        ]
      },
      {
        "ota": 2,
        "search_date_group": [
          {
            "max_code": "102246936",
            "max_price": 4500,
            "min_code": "102246934",
            "min_price": 1500,
            "search_date": ISODate("2019-09-10T00:00:00Z")
          },
          {
            "max_code": "02246936",
            "max_price": 14500,
            "min_code": "02246934",
            "min_price": 11500,
            "search_date": ISODate("2019-09-09T00:00:00Z")
          }
        ]
      }
    ]
  }

你可以在这里测试它here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接