Reputation: 19841
I have a collection with documents, of that structure
{
type: 'a',
date: '2014-01-04'
},
{
type: 'b',
date: '2014-01-04'
},
{
type: 'b',
date: '2014-01-04
},
{
type: 'c',
date: '2014-01-03'
},
{
type: 'a',
date: '2014-01-03'
}
I want to aggregate that data by date and type (group by date and count by type):
{
date: '2014-01-04': {
'a': 1,
'b': 2
},
date: '2014-01'03': {
'a': 1,
'c': 1
}
}
I have aggregate function, like this
db.items.aggregate([
{
$match: { user: user },
},
{
$group: { _id: {date: '$date'}, count: {$sum: 1}, services: {$push: '$type'}}
}
], function (err, results) {
But doing that I still need to reduce
results by services.
Can this be done with one aggregation query?
Upvotes: 2
Views: 2449
Reputation: 36794
You can of course group by more than one field:
{ $group: { _id: { date: '$date', services: '$services' } }
But that is not what you want it seems. You can not every easily convert data to keys, unless you can do that all by hand. The following query would be an option:
db.test.aggregate( [
{ $group: {
'_id' : { date: '$date' },
a: { $sum: {
$cond: [ { $eq: [ '$type', 'a' ] }, 1, 0 ]
} },
b: { $sum: {
$cond: [ { $eq: [ '$type', 'b' ] }, 1, 0 ]
} },
c: { $sum: {
$cond: [ { $eq: [ '$type', 'c' ] }, 1, 0 ]
} },
} },
{ $project: {
_id: 0,
date: '$_id.date',
a: '$a',
b: '$b',
c: '$c',
} }
] );
You will need to manually add a line for each new type.
Upvotes: 3
Reputation: 26032
By assuming you have fixed number of types, you can solve it as follows :
db.collection.aggregate(
{$group : {_id : "$date",
a:{$sum:{$cond:[{$eq:['$type','a']},1,0]}},
b:{$sum:{$cond:[{$eq:['$type','b']},1,0]}},
c:{$sum:{$cond:[{$eq:['$type','c']},1,0]}}
}},
{$project : {_id : 0, date : "$_id", a: "$a", b : "$b", c : "$c"}}
)
Upvotes: 1