【问题标题】:Using weighted average with MongoDB and $group对 MongoDB 和 $group 使用加权平均值
【发布时间】:2017-10-13 22:52:35
【问题描述】:

在使用 $group 时,有什么方法可以使用加权平均值而不是 $avg 组累加器?我使用这个(How do I calculate a weighted average in mongoDB using aggregation framework?)作为加权平均值,但我得到的错误是“字段 'id:WAVG_A' 必须指定一个累加器”。是否有某种技巧可以使用投影而不是组累加器?

我的聚合 JSON 的一个子集在这里:

{
   "$group":{
      "_id":{
         "id:DIM_1":"$id:DIM_1",
         "id:DIM_2":"$id:DIM_2"
      },
      "id:WAVG_A":{
         "$group":{
            "_id":"weighted average",
            "nu":{
               "$sum":{
                  "$multiply":[
                     "$id:WAVG_A",
                     "$id:MET_A"
                  ]
               }
            },
            "de":{
               "$sum":"$id:MET_A"
            }
         },
         "$project":{
            "average":{
               "$divide":[
                  "$nu",
                  "$de"
               ]
            }
         }
      },
      "id:MET_A":{
         "$sum":"$id:MET_A"
      }
   }
}

编辑

为了简化事情,让我尝试使用类似于 mongo 网站上提供的示例的数据来解释我的问题。假设您有如下数据:

{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "weight" : 1, "date" : ISODate("2014-03-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "weight" : 1, "date" : ISODate("2014-03-01T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "weight" : 2, "date" : ISODate("2014-03-15T09:00:00Z") }
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "weight" : 3, "date" : ISODate("2014-04-04T11:21:39.736Z") }
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "weight" : 3, "date" : ISODate("2014-04-04T21:23:13.331Z") }

在聚合数据时不要使用 $avg,而是要使用加权平均值 (https://support.microsoft.com/en-ca/help/214049/how-to-calculate-weighted-averages-in-excel)。如果本机支持,它可能如下所示:

db.sales.aggregate(
   [
      {
        $group : {
           _id : { month: { $month: "$date" }, day: { $dayOfMonth: "$date" }, year: { $year: "$date" } },
           totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } },
           averageQuantity: { $weighted_avg: { $value : "$quantity", $weight: "$weight" },
           count: { $sum: 1 }
        }
      }
   ]
)

这个想法是,当你平均它时,你有一个平均值和一个权重。 Mongo 支持加权平均值,因为它支持数学运算,如 How do I calculate a weighted average in mongoDB using aggregation framework? 中的乘法和除法。但我不知道在聚合数据时如何使用加权平均值。当我想使用 $group 时,如何应用来自How do I calculate a weighted average in mongoDB using aggregation framework? 的答案。该答案的问题在于它是一个 $group 和一个 $project 并且您似乎不能将其用作 $group 的累加器。

【问题讨论】:

  • 考虑到问题是您的语法完全不正确,那么“子集”确实不是描述您的问题的最佳方式。相反,您应该提供一些源数据、您的预期结果以及您希望如何获得这些结果的解释。您不能将 $group 嵌套在 $group 中,因此不要显示“尝试的一部分”,而是显示需要发生的事情。

标签: mongodb


【解决方案1】:

所以我有一个解决我的问题的方法。我试图一次做太多事情。我的解决方案是将组和项目分解为两个单独的步骤,同时将分子和分母放入临时值中并且它起作用了。

{
   "$group":{
      "_id":{
         "id:DIM_1":"$id:DIM_1",
         "id:DIM_2":"$id:DIM_2"
      },
      "id:WAVG_A??num":{
         "$sum":{
            "$multiply":[
               "$id:WAVG_A",
               "$id:MET_A"
            ]
         }
      },
      "id:WAVG_A??den":{
         "$sum":"$id:MET_A"
      },
      "id:MET_A":{
         "$sum":"$id:MET_A"
      }
   }
}

然后

{
   "$project":{
      "id:DIM_1":"$_id.id:DIM_1",
      "id:DIM_2":"$_id.id:DIM_2",
      "id:WAVG_A":{
         "$cond":[
            {
               "$eq":[
                  "$id:WAVG_A??den",
                  0
               ]
            },
            0,
            {
               "$divide":[
                  "$id:WAVG_A??num",
                  "$id:WAVG_A??den"
               ]
            }
         ]
      },
      "id:MET_A":"$id:MET_A"
   }

【讨论】:

猜你喜欢
  • 2021-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
相关资源
最近更新 更多