【问题标题】:MongoDB SELECT COUNT GROUP BYMongoDB 选择计数组
【发布时间】:2014-05-31 17:34:51
【问题描述】:

我正在玩 MongoDB,试图弄清楚如何做一个简单的

SELECT province, COUNT(*) FROM contest GROUP BY province

但我似乎无法使用聚合函数来计算它。我可以使用一些非常奇怪的组语法来做到这一点

db.user.group({
    "key": {
        "province": true
    },
    "initial": {
        "count": 0
    },
    "reduce": function(obj, prev) {
        if (true != null) if (true instanceof Array) prev.count += true.length;
        else prev.count++;
    }
});

但是使用聚合函数有更简单/更快的方法吗?

【问题讨论】:

    标签: mongodb group-by aggregation-framework


    【解决方案1】:

    这将是使用aggregate 的更简单方法:

    db.contest.aggregate([
        {"$group" : {_id:"$province", count:{$sum:1}}}
    ])
    

    【讨论】:

    • 当我尝试 "errmsg" : "exception: A pipeline stage specification object must contain exactly one field.", 时收到一条错误消息?
    • 你如何分组排序呢?我想按 -1 对计数进行排序
    • @FilipBartuzi 在文档页面中有一个示例,您必须向管道添加排序操作,如{ $sort: { count: -1 } }
    • 我遇到了与@Steven 相同的异常,这是因为我只复制粘贴了第 2 行并省略了周围的方括号。
    【解决方案2】:

    我需要根据聚合函数的结果进行一些额外的操作。最后,我找到了一些聚合函数的解决方案,并根据 MongoDB 中的结果进行操作。我有一个集合Request,字段为request, source, status, requestDate

    单字段分组方式和计数:

    db.Request.aggregate([
        {"$group" : {_id:"$source", count:{$sum:1}}}
    ])
    

    多个字段分组和计数:

    db.Request.aggregate([
        {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}}
    ])
    

    使用字段排序的多个字段分组和计数:

    db.Request.aggregate([
        {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}},
        {$sort:{"_id.source":1}}
    ])
    

    Multiple Fields Group By & Count with Sort using Count:

    db.Request.aggregate([
        {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}},
        {$sort:{"count":-1}}
    ])
    

    【讨论】:

    • 你能解释一下{_id:{source:"$source",status:"$status"}这个吗?
    • 基本上,字段“_id”是每个文档的唯一标识符。该字段接受一个表达式。您可以通过根据分组条件组合多个字段来定义字段的值。您将在链接中找到有关该字段的更多详细信息:docs.mongodb.com/manual/reference/operator/aggregation/group/…
    【解决方案3】:

    如果您需要多个列进行分组,请遵循此模型。在这里,我正在通过statustype 进行计数:

      db.BusinessProcess.aggregate({
        "$group": {
            _id: {
                status: "$status",
                type: "$type"
            },
            count: {
                $sum: 1
            }
        }
       })
    

    【讨论】:

    【解决方案4】:

    从 MongoDB 3.4 开始,您可以使用 $sortByCount 聚合。

    根据指定表达式的值对传入文档进行分组,然后计算每个不同组中的文档计数。

    https://docs.mongodb.com/manual/reference/operator/aggregation/sortByCount/

    例如:

    db.contest.aggregate([
        { $sortByCount: "$province" }
    ]);
    

    【讨论】:

    • 这里可能值得注意的是,$sortByCount 实际上是一个“伪运算符”,就像从 MongoDB 3.4 引入的更多聚合阶段运算符一样。他们真正做的只是扩展到各自的聚合阶段。在这种情况下,$group$sum: 1 如现有答案所示,还有一个额外的 $sort 阶段。除了“键入更少的代码” 之外,它们没有提供任何优势,这可能更具描述性,也可能不更具描述性(如果您喜欢这类事情)。恕我直言,代码中不同的$group$sort 阶段更具描述性,而且确实更灵活。
    【解决方案5】:

    另外,如果您需要限制可以使用的分组:

    db.events.aggregate( 
        {$match: {province: "ON"}},
        {$group: {_id: "$date", number: {$sum: 1}}}  
    )
    

    【讨论】:

      【解决方案6】:

      这种类型的查询对我有用:

       db.events.aggregate({$group: {_id : "$date", number:  { $sum : 1} }} )
      

      http://docs.mongodb.org/manual/tutorial/aggregation-with-user-preference-data/

      【讨论】:

        【解决方案7】:
            db.contest.aggregate([
                { $match:{.....May be some match criteria...}},
                { $project: {"province":1,_id:0}},
                { $sortByCount: "$province" }
            ],{allowDiskUse:true});
        

        MongoDB 对内存的排序操作有 32 MB 的限制,使用 allowDiskUse : true 这个选项,当你预先暴露这个查询数百万的数据时,它将在磁盘级别而不是在内存中排序。 MongoDB 聚合管道有 100MB 的限制,所以使用 $project 来减少流向下一个管道的数据。 如果您使用的是小数据,则无需使用 allowDiskUse 选项。

        【讨论】:

          【解决方案8】:

          Mongo 5.0开始,我们也可以使用{ $count: { } } 作为{ $sum : 1 }的别名:

          // { "province" : "Champagne-Ardenne" }
          // { "province" : "Champagne-Ardenne" }
          // { "province" : "Haute-Normandie"   }
          db.collection.aggregate([
            { $group: { _id: "$province", count: { $count: {} } } }
          ])
          // { "_id" : "Champagne-Ardenne", "count" : 2 }
          // { "_id" : "Haute-Normandie",   "count" : 1 }
          

          【讨论】:

            【解决方案9】:

            对我有用的 Mongo shell 命令:

            db.getCollection(<collection_name>).aggregate([{"$match": {'<key>': '<value to match>'}}, {"$group": {'_id': {'<group_by_attribute>': "$group_by_attribute"}}}])
            

            【讨论】:

              猜你喜欢
              • 2016-01-05
              • 1970-01-01
              • 1970-01-01
              • 2017-05-11
              • 2017-01-28
              • 2020-11-27
              • 2012-05-12
              • 2019-12-27
              相关资源
              最近更新 更多