麻烦在mongodb聚合查询中使用$ group两次

时间:2014-07-11 17:01:31

标签: node.js mongodb aggregation-framework

首先让我说我是mongo和node.js的新手。对于我工作的每个客户,我正在查看过去一周的流量,以查找六个变量的最大值和最小值以及它们的日期。现在mongo聚合负责一些工作,但我相信它可以做更多。现在我的管道如下:

  1. $ match - 仅返回过去一周内的文件
  2. $ group - 按客户和按日期分组
  3. $ project - 计算一些值
  4. 文件以下列庄园退回:

    { _id: 
       { client: "aRandomClientNameWouldBeHere",
         date: Thu Jun 04 46370 00:00:00 GMT-0400 (EDT) },
      impSales: 0,
      pixSales: 0,
      apiSales: 0,
      s2sSales: 0,
      clicks: 3,
      impressions: 0 }
    

    我无法在管道中添加另一个$ group阶段,只对客户进行分组并获取每个字段的最大值和最小值的日期。

    我需要这样的东西:

    $group: { 
      _id: "$client" ,
      maxImpSales: { $max: impSales },
      maxImpSalesDate : { ??? },
      minImpSales: { $min: impSales },
      minImpSalesDate : { ??? },
      ...
    }
    

    然而,由于两个原因,我无法让它工作。

    1. 我不知道如何按客户端进行分组,因为客户端现在与日期一起位于_id字段中。 (即我使用_id:“$ client”或_id:_id.client还是别的什么?)
    2. 如何嵌入min和max发生的日期?
    3. 我如何做1& 2?谢谢。下面是我的3阶段管道

      {
        $match:
        {
          date:
          {
            $gte: _.last(dutil.lastXDates(6))
          }
        }
      },
      {
        $group:
        {
          _id:
          {
            client: "$client",
            date: "$date"
          },
          z1is: { $sum: "$actions.sales.import.z1.count" },
          z2is: { $sum: "$actions.sales.import.z2.count" },
          z3is: { $sum: "$actions.sales.import.z3.count" },
          z1ps: { $sum: "$actions.sales.pixel.z1.count" },
          z2ps: { $sum: "$actions.sales.pixel.z2.count" },
          z3ps: { $sum: "$actions.sales.pixel.z3.count" },
          z1as: { $sum: "$actions.sales.apiOnly.z1.count" },
          z2as: { $sum: "$actions.sales.apiOnly.z2.count" },
          z3as: { $sum: "$actions.sales.apiOnly.z3.count" },
          z1ss: { $sum: "$actions.sales.s2s.z1.count" },
          z2ss: { $sum: "$actions.sales.s2s.z2.count" },
          z3ss: { $sum: "$actions.sales.s2s.z3.count" },
          z1ic: { $sum: "$actions.click.import.z1.count" },
          z2ic: { $sum: "$actions.click.import.z2.count" },
          z3ic: { $sum: "$actions.click.import.z3.count" },
          z1pc: { $sum: "$actions.click.pixel.z1.count" },
          z2pc: { $sum: "$actions.click.pixel.z2.count" },
          z3pc: { $sum: "$actions.click.pixel.z3.count" },
          z1ac: { $sum: "$actions.click.apiOnly.z1.count" },
          z2ac: { $sum: "$actions.click.apiOnly.z2.count" },
          z3ac: { $sum: "$actions.click.apiOnly.z3.count" },
          z1sc: { $sum: "$actions.click.s2s.z1.count" },
          z2sc: { $sum: "$actions.click.s2s.z2.count" },
          z3sc: { $sum: "$actions.click.s2s.z3.count" },
          z1ii: { $sum: "$actions.display.import.z1.count" },
          z2ii: { $sum: "$actions.display.import.z2.count" },
          z3ii: { $sum: "$actions.display.import.z3.count" },
          z1pi: { $sum: "$actions.display.pixel.z1.count" },
          z2pi: { $sum: "$actions.display.pixel.z2.count" },
          z3pi: { $sum: "$actions.display.pixel.z3.count" },
          z1ai: { $sum: "$actions.display.apiOnly.z1.count" },
          z2ai: { $sum: "$actions.display.apiOnly.z2.count" },
          z3ai: { $sum: "$actions.display.apiOnly.z3.count" },
          z1si: { $sum: "$actions.display.s2s.z1.count" },
          z2si: { $sum: "$actions.display.s2s.z2.count" },
          z3si: { $sum: "$actions.display.s2s.z3.count" }
        }
      },
      {
        $project:
        {
          totalCountImpSales: { $add: ["$z1is", "$z2is", "$z3is"] },
          totalCountImpClicks: { $add: ["$z1ic", "$z2ic", "$z3ic"] },
          totalCountImpImpressions: { $add: ["$z1ii", "$z2ii", "$z3ii"] },
          totalCountPixSales: { $add: ["$z1ps", "$z2ps", "$z3ps"] },
          totalCountPixClicks: { $add: ["$z1pc", "$z2pc", "$z3pc"] },
          totalCountPixImpressions: { $add: ["$z1pi", "$z2pi", "$z3pi"] },
          totalCountApiSales: { $add: ["$z1as", "$z2as", "$z3as"] },
          totalCountApiClicks: { $add: ["$z1ac", "$z2ac", "$z3ac"] },
          totalCountApiImpressions: { $add: ["$z1ai", "$z2ai", "$z3ai"] },
          totalCountS2sSales: { $add: ["$z1ss", "$z2ss", "$z3ss"] },
          totalCountS2sClicks: { $add: ["$z1sc", "$z2sc", "$z3sc"] },
          totalCountS2sImpressions: { $add: ["$z1si", "$z2si", "$z3si"] }
        }
      }
      

1 个答案:

答案 0 :(得分:1)

有一种解决方法。在$sort之后添加$project阶段,然后使用$group阶段中的$first$last运算符来获取最小值和最大值。那就是:

...
// Sort by impSales ascending
{
    $sort: { impSales: 1}
},
{
$group: { 
  _id: "$_id.client" ,
  maxImpSales: { $last: "$impSales" },
  maxImpSalesDate : { $last: "$_id.date" },
  minImpSales: { $first: "$impSales" },
  minImpSalesDate : { $first: "$_id.date" },
  ...
}
}
...