【问题标题】:Mongoose get count of items in array field across all docsMongoose 获取所有文档中数组字段中的项目数
【发布时间】:2018-04-19 13:50:28
【问题描述】:

刚开始使用聚合或 map/reduce。我想要所有文档中名为“标签”的数组字段中的项目数。我正在使用猫鼬。谢谢!

例子:

文档 1

tags: ['A', 'B', 'C', 'D']

文档 2

tags: ['A', 'B']

文档 3

tags: ['D']

结果:{A: 2, B: 2, C: 1, D: 2}

还想要数组项的总数,以便我可以计算百分比(例如,A = 2/7)

【问题讨论】:

    标签: mongodb mongoose


    【解决方案1】:

    尽我所能,您可以这样做:

    db.getCollection('tags').aggregate([
      { "$unwind": "$tags" },
      { "$group": {
        "_id": "$tags",
        "count": { "$sum": 1 }  
      }},
      { "$sort": { "_id": 1 } },
      { "$group": {
        "_id": null,
        "tags": { "$push": { "k": "$_id", "v": "$count" } }  
      }},
      { "$replaceRoot": {
        "newRoot": { 
          "$mergeObjects": [ 
            { "$arrayToObject": "$tags" },
            { "total": { "$sum": "$tags.v" } }
          ]
        }
      }}
    ])
    

    如果您没有 MongoDB 3.6 功能,您可以像这样简单地转换输出:

    db.getCollection('tags').aggregate([
      { "$unwind": "$tags" },
      { "$group": {
        "_id": "$tags",
        "count": { "$sum": 1 }  
      }},
      { "$sort": { "_id": 1 } },
      { "$group": {
        "_id": null,
        "tags": { "$push": { "k": "$_id", "v": "$count" } }  
      }}
    ]).map( d => 
      Object.assign(
        d.tags.reduce((acc,curr) => Object.assign(acc, { [curr.k]: curr.v }), {}),
        { total: d.tags.reduce((acc,curr) => acc + curr.v, 0) }
      )
    )
    

    无论哪种方式都会产生:

    {
        "A" : 2.0,
        "B" : 2.0,
        "C" : 1.0,
        "D" : 2.0,
        "total" : 7.0
    }
    

    如果您想要其中的“百分比”,您可以对输出进行后期处理,因为所有数字都已经存在,或者只是更改处理。

    对于 MongoDB 3.6

    db.getCollection('tags').aggregate([
      { "$unwind": "$tags" },
      { "$group": {
        "_id": "$tags",
        "count": { "$sum": 1 }  
      }},
      { "$sort": { "_id": 1 } },
      { "$group": {
        "_id": null,
        "tags": { "$push": { "k": "$_id", "v": "$count" } } ,
        "total": { "$sum": "$count" }
      }},
      { "$replaceRoot": {
        "newRoot": { 
          "$mergeObjects": [ 
            { "$arrayToObject": {
              "$map": {
                "input": "$tags",
                "in": {
                  "k": "$$this.k",
                  "v": {
                    "count": "$$this.v",
                    "perc": { "$multiply": [{ "$divide": [ "$$this.v", "$total" ] }, 100 ] }   
                  }
                }   
              }
            }},
            { "total": "$total" }
          ]
        }
      }}
    ])
    

    或更低版本,仍在处理输出:

    db.getCollection('tags').aggregate([
      { "$unwind": "$tags" },
      { "$group": {
        "_id": "$tags",
        "count": { "$sum": 1 }  
      }},
      { "$sort": { "_id": 1 } },
      { "$group": {
        "_id": null,
        "tags": { "$push": { "k": "$_id", "v": "$count" } },
        "total": { "$sum": "$count" } 
      }}
    ]).map( d =>
      Object.assign(
        d.tags.reduce((acc,curr) => 
          Object.assign(acc, { [curr.k]: { count: curr.v, perc: curr.v / d.total  * 100 } }),
          {}
        ),
        { total: d.total }
      )
    )
    

    输出包括每个分组键上的两个键:

    {
        "A" : {
            "count" : 2.0,
            "perc" : 28.5714285714286
        },
        "B" : {
            "count" : 2.0,
            "perc" : 28.5714285714286
        },
        "C" : {
            "count" : 1.0,
            "perc" : 14.2857142857143
        },
        "D" : {
            "count" : 2.0,
            "perc" : 28.5714285714286
        },
        "total" : 7.0
    }
    

    请注意,MongoDB shell 对现代 JavaScript 功能有些限制。在现代 JavaScript 环境中,例如最近发布的 Nodejs,您可以缩短转换时间:

    result.map(({ _id, tags, ...d }) =>
      ({
        ..tags.reduce((acc,curr) => 
          ({ ...acc, [curr.k]: { count: curr.v, perc: curr.v / d.total  * 100 }),
          {}
        ),
        ...d
      })
    )
    

    【讨论】:

    • 谢谢两位。这对 mongo 很有效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多