Mongodb group and sort

前端 未结 8 2004
隐瞒了意图╮
隐瞒了意图╮ 2020-12-09 15:31

How can I translate the following Sql query for Mongo?:

select a,b,sum(c) csum from coll wh         


        
相关标签:
8条回答
  • 2020-12-09 16:07

    I want to add the following query, as an example, it may be useful in case of two groupings.

    Query:

    db.getCollection('orders').aggregate([
        {$match:{
            tipo: {$regex:"[A-Z]+"}
            }
        },
        {$group:
            { 
                _id:{
                    codigo:"1",
                    fechaAlta:{$substr:["$fechaAlta",0,10]},
                },
                total:{$sum:1}
            }
        },
        {$sort:
            {"_id":1}
        },
        {$group:
            {
                _id:"$_id.codigo",
                fechasAltas:
                {
                    $push:
                    {
                        fechaAlta:"$_id.fechaAlta",
                        total:"$total"
                    }
                },
                totalGeneral:{$sum:"$total"}
            }
        }
    ]); 
    

    Response:

    {
    "_id" : "1",
    "fechasAltas" : [ 
        {
            "fechaAlta" : "1940-01-01",
            "total" : 13.0
        }, 
        {
            "fechaAlta" : "2007-05-14",
            "total" : 115.0
        }, 
        {
            "fechaAlta" : "2008-09-30",
            "total" : 58.0
        }, 
    
        .
        .
        .
    ],
    "totalGeneral" : 50620.0
    }       
    
    0 讨论(0)
  • 2020-12-09 16:14

    Inspired by this example on mongo's website.

    GENERATE DUMMY DATA:

    > db.stack.insert({a:1,b:1,c:1,active:1})
    > db.stack.insert({a:1,b:1,c:2,active:0})
    > db.stack.insert({a:1,b:2,c:3,active:1})
    > db.stack.insert({a:1,b:2,c:2,active:0})
    > db.stack.insert({a:2,b:1,c:3,active:1})
    > db.stack.insert({a:2,b:1,c:10,active:1})
    > db.stack.insert({a:2,b:2,c:10,active:0})
    > db.stack.insert({a:2,b:2,c:5,active:1})
    

    MONGO QUERY:

    > db.stack.aggregate(
    ... {$match:{active:1}},
    ... {$group:{_id:{a:"$a", b:"$b"}, csum:{$sum:"$c"}}},
    ... {$sort:{"_id.a":1}})
    

    RESULT:

    {"result" : [
        {"_id" : {"a" : 1,"b" : 2},"csum" : 3},
        {"_id" : {"a" : 1,"b" : 1},"csum" : 1},
        {"_id" : {"a" : 2,"b" : 2},"csum" : 5},
        {"_id" : {"a" : 2,"b" : 1},"csum" : 13}
    ],"ok" : 1}
    

    (NOTE: I reformatted the shell result a bit so it is more readable)

    0 讨论(0)
  • 2020-12-09 16:17

    The mongodb aggregation API seems to have changed. Now you would do

    db.coll.aggregate([
      {
         $group: { 
            _id: "$a", 
            countA: { $sum: 1}, 
            sumC:{ $sum: "$c"}, 
         }
      },
      {
        $sort:{a:1}
      }
    ])
    

    Note the Array syntax for the argument to aggregate(). You'd also add things link $match, $limit etc. as elements of this array.

    0 讨论(0)
  • 2020-12-09 16:18

    Adding to previous answers, if you want to sort on the sum (the result of the aggregate) instead of on the actual column, you can do this:

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

    This would be the equivalent of the following standard-SQL-ish syntax:

    select col_a, count(col_a) as b
    from table
    group by col_a
    order by b desc
    
    0 讨论(0)
  • 2020-12-09 16:20

    Until the Aggregation Framework is release in MongoDB 2.1, the call for group as in this answer, is rather slow, since it is using the JavaScript part of the DB.

    You can use a faster approach for counting groups:

    var res = [];
    for( var cur_a = db.coll.distinct('a'); cur_a.hasNext(); ) {
      var a = cur_a.next();
      for( var cur_b = db.coll.distinct('b'); cur_b.hasNext(); ) {
        var b = cur_b.next();
        res.push({ 'a': a, 'b' : b 'count': db.coll.count({'a':a,'b':b})}
      }
    }
    

    It will be faster if you have indexes on a and b

    db.coll.ensureIndex({'a':1,'b':1})
    
    0 讨论(0)
  • 2020-12-09 16:25

    Using the aggregate framework, you can do the following:

    db.coll.aggregate({ 
        $group: { 
            _id: "$a", 
            countA: { $sum: 1}, 
            sumC:{ $sum: "$c"}, 
        },
        $sort:{a:1}
    });
    

    However, if you have too much data you may get the following error message:

    {
        "errmsg" : "exception: aggregation result exceeds maximum document size (16MB)",
        "code" : 16389,
        "ok" : 0
    }
    

    See more about SQL to Mongo translation here: http://docs.mongodb.org/manual/reference/sql-aggregation-comparison/

    0 讨论(0)
提交回复
热议问题