mongodb-同一文档的两个依赖聚合

mongodb-同一文档的两个依赖聚合,mongodb,aggregation-framework,Mongodb,Aggregation Framework,假设提供了以下集合: {"Year" : 2014, "State" : "AZ", "Distributer" : "AAA", "Revenu_category_A" : 300, "Revenu_category_B" : 42, "Revenu_category_C" : 75} {"Year" : 2015,

假设提供了以下集合:

{"Year" : 2014, "State" : "AZ", "Distributer" : "AAA", "Revenu_category_A" : 300, "Revenu_category_B" : 42, "Revenu_category_C" : 75}
{"Year" : 2015, "State" : "AZ","Distributer" : "AAA","Revenu_category_A" : 475, "Revenu_category_B" : 78, "Revenu_category_C" : 21}
{ "Year" : 2014, "State" : "NY","Distributer" : "AAA","Revenu_category_A" : 74, "Revenu_category_B" : 44, "Revenu_category_C" : 13}
{"Year" : 2015, "State" : "NY","Distributer" : "BBB","Revenu_category_A" : 234, "Revenu_category_B" : 41, "Revenu_category_C" : 433}
对于上述每一个分销商,我想找出贡献最小收入的类别,以及分销商在所有年份中从该类别获得最多收入的州

例如,参考上述数据。如果我们查看分销商
AAA
,并计算每个类别的总收入。结果如下:

{"Distributer" : "AAA", "Least_Revenue_category": "Revenu_category_A", "State_with_most_revenue" : "AZ"}
{"Distributer" : "BBB"...}...
A类
的总收入为:849
B类
的总收入为:164
C类的总收入为:109

根据该结果,
C类
对分销商总收入的贡献最低
AAA
(总收入109)

然后我们需要找到
类别C
为分销商
AAA
产生最多收入的州。该州是亚利桑那州,总收入为96英镑,而纽约州仅为该类收入创造13英镑

因此,预期结果如下所示:

{"Distributer" : "AAA", "Least_Revenue_category": "Revenu_category_A", "State_with_most_revenue" : "AZ"}
{"Distributer" : "BBB"...}...

要使用聚合实现这一点,您需要一种方法来确定哪些字段是收入类别。管道阶段可能是:

  • 将收入类别字段收集到键值对数组中
  • 展开阵列
  • 按经销商、州和类别分组,并计算每个类别的总收入
  • 按收入递减排序
  • 按经销商和类别分组,存储第一条记录(按州最大值),并计算每个类别的总收入
  • 按收入递增排序
  • 按分发者分组,捕获每个分发者的第一条记录。这将是该分销商在该类别中的最小类别和最高状态
如果正则表达式匹配可以识别这些字段,则可能如下所示:

db.collection.aggregate([
  {$addFields: {
      fields: {
        $filter: {
          input: {$objectToArray: "$$ROOT"},
          cond: {
            "$regexMatch": {
              "input": "$$this.k",
              "regex": "^Revenu"
            }
          }
        }
      }
   }},
  {$unwind: "$fields"},
  {$group: {
      _id: {
        distributer: "$Distributer",
        state: "$State",
        category: "$fields.k"
      },
      stateTotal: {$sum: "$fields.v"}
  }},
  {$sort: {stateTotal: -1}},
  {$group: {
      _id: {
        distributer: "$_id.distributer",
        category: "$_id.category"
      },
      most: {
        $first: {
          state: "$_id.state",
          stateTotal: "$stateTotal"
        }
      },
      catTotal: {$sum: "$stateTotal"}
  }},
  {$sort: {catTotal: 1}},
  {$group: {
      _id: "$_id.distributer",
      "Least_Revenue_category": {$first: "$_id.category"},
      "State_with_most_revenue": {$first: "$most.state"}
  }},
  {$project: {
      _id: 0,
      Distributer: "$_id",
      "Least_Revenue_category": 1,
      "State_with_most_revenue": 1
  }}
])

您能否在问题中添加来自该文档的预期结果。为了使问题更清楚,我对其进行了编辑,并添加了一个具有预期结果的示例。A类到C类字段将是动态的或始终固定的?可以是动态的,但为了简单起见,它可以固定。换句话说,为了简单起见,我们将把这些类别看作三个固定的类别。它非常漂亮,并且给出了解决方案。如果类别是固定的呢?如果不使用正则表达式,解决方案会是什么样子?您所需要的只是
cond
中的一些布尔表达式,对于要视为类别的字段名,该表达式将返回true,而对于其他字段名,该表达式将返回false。这可以是
$eq
$in
$or
$not
$regex
,等等中的任何一个。几乎可以在那里使用任何逻辑查询运算符。