Mongodb聚合与多个分组依据

时间:2019-11-27 07:42:05

标签: mongodb group-by aggregation-framework

我有一个mongodb收集测试。数据看起来像这样-

SELECT Customers.CustomerName as 'Name',
COUNT(*) AS 'Order Count'
FROM Orders
LEFT JOIN Customers
    ON Orders.CustomerID = Customers.CustomerID
GROUP BY Customers.CustomerName 

我想编写一个查询,该查询可以给出类似-

的结果
{ 
    "_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对文档进行分组,然后应再次使用ota对每个子组进行分组。此外,应使用search_date将这些子分组。对于每个search_date,我需要max_price,max_code和min_price,min_code。 根据我的理解,我需要执行“嵌套”分组操作才能实现此结果。

我是Mongodb的新用户,并尝试编写查询-

{ 
    "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"
        }]
    }]
}

但还没有达到要求。 任何人都可以提供一些提示/想法如何实现这一目标。

1 个答案:

答案 0 :(得分:1)

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

技巧是双重的:

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

以下是您需要的查询:

function createWindow () {
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })
  win.loadFile('index.html')

  // HERE I AM OPENING THE DEV TOOLS
  win.webContents.openDevTools()

  win.on('closed', () => {
    win = null
  })
}

它将完全输出您需要的内容:

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"
        }
      }
    }
  }
])

您可以here对其进行测试。