MongoDB 通过嵌套字段进行聚合并按另一个字段进行计数

标签 mongodb aggregation-framework facet

我有以下三个不同的文档

{
  "category" : "aaaaa",
  "summary" : {
    "details" : {
      "city" : "abc"
      "year_of_reg" : "2012",
      "dept" : "dev"
    }
  }
}

{
  "category" : "bbbb",
  "summary" : {
    "details" : {
      "city" : "abc",
      "year_of_reg" : "2016",
      "dept" : "dev"
    }
  }
}

{
  "category" : "aaaaa",
  "summary" : {
    "details" : {
      "dept" : "ui",
      "year_of_reg" : "2018"
    }
  }
}

我想根据摘要下详细信息中的可用键对结果进行分组,并根据类别进行计数。最终结果应该如下所示

{
  "dep_dev":[
      {
         "category":"aaaaa",
         "count":1.0
      },
      {
         "category":"bbbb",
         "count":1.0
      }
   ],
   "dep_ui":[
      {
         "category":"aaaaa",
         "count":1.0
      }
   ],
   "year_of_reg_2012":[
      {
         "category":"aaaaa",
         "count":1.0
      }
   ],
   "year_of_reg_2016":[
      {
         "category":"bbbb",
         "count":1.0
      }
   ],
   "year_of_reg_2018":[
      {
         "category":"aaaaa",
         "count":1.0
      }
   ],      
   "city_abc":[
      {
         "category":"aaaaa",
         "count":1.0
      },
      {
         "category":"bbbb",
         "count":1.0
      }
   ]
}

如何在 mongo 聚合中实现这一点?这可以使用方面来完成吗? 如何聚合动态生成输出 key ?有没有可能使用单个 mongo 查询获取详细信息下的所有可用键?

最佳答案

您需要运行以下聚合管道才能获得所需的结果:

db.getCollection('test').aggregate([
    /*
    1. Create a field with an array of the summary details key concatenated with their 
       corresponding values. 
    */
    { "$addFields": { 
        "summary": {
            "$map": {
                "input": { "$objectToArray": "$summary.details" },
                "as": "el",
                "in": {
                    "$concat": ["$$el.k", "_", "$$el.v"]
                }
            }
        }
    } },

    /*
    2. Flatten the new array to produce a copy of each document per array entry. 
    */
    { "$unwind": "$summary" },

    /*
    3. Group the documents initially by the key and category. 
    */
    { "$group": {
        "_id": { 
            "key": "$summary",
            "category": "$category"
        },
        "count": { "$sum": 1 }
    } },

    /*
    4. Group the input documents from the previous pipeline by the key and aggregate the 
       category and corresponding counts  
    */
    {  "$group": {
        "_id": "$_id.key",
        "counts": {
            "$push": {
                "category": "$_id.category",
                "count": "$count"
            }
        }
    } },

    /*
    4. Calculate accumulated values for all the input documents as a whole.
    */
    {  "$group": {
        "_id": null,
        "counts": {
            "$push": {
                "k": "$_id",
                "v": "$counts"
            }
        }
    } },
    { "$replaceRoot": {
        "newRoot": { "$arrayToObject": "$counts" }
    } } 
])

关于MongoDB 通过嵌套字段进行聚合并按另一个字段进行计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51787208/

相关文章:

mongodb - MongoDB中的索引列表?

mongodb - 如何根据数组元素的索引对文档进行分组?

node.js - MongoDB - $lookup 和 $aggregate 位于 2 个集合中

ElasticSearch - 字符串字段长度的统计方面

javascript - Mongo : Is it a good practice to do collection. find() 返回主节点上的所有项目

c# - Mongo C# Driver 2.0 聚合组异常

solr - 从 Solr 结果中过滤掉不相关的方面

ruby-on-rails - Rails & Sunspot 刻面和过滤

mongodb - 在具有只读FS的Docker中运行Mongodb

mongodb - $divide 累加器是一元运算符