How to Change output format when using group in aggregation mongodb - mongodb

I Need to change the out put format of following mongodb query.
Query
db.Response.aggregate([{
"$match": {
"$and": [{
"job_details.owner_id" : 482,
}, {
"job_details.owner_type" : 'searches',
}],
},
},
{
"$group": {
"_id": "$candidate_sublocation_name_string",
"count": {
"$sum": 1,
},
},
}])
Actual Out Put
{ "_id" : "Central Delhi ", "count" : 1 }
{ "_id" : "Adyar ", "count" : 1 }
{ "_id" : "Bommanahalli", "count" : 2 }
{ "_id" : "DLF Phase 3 ", "count" : 2 }
{ "_id" : "Aai Colony", "count" : 1 }
Needed Out Put
{ "Central Delhi" : 1 }
{ "Adyar" : 1 }
{ "Bommanahalli" : 2 }
{ "DLF Phase 3 ": 2 }
{ "Aai Colony": 1 }
Is it possible to change the out put format like this..?

Related

Does MongoDB support aggregate queries on the result of the aggregate query?

I have an aggregate query that returns the count of records a property has.
db.collection.aggregate([
{
$group : {
_id : "$propertyId",
count: { $sum: 1 }
}
},
{
$sort : { count: 1 }
}
],
{
allowDiskUse:true
});
This gives me a result that looks like this.
{ "_id" : 1234, "count" : 1 }
{ "_id" : 1235, "count" : 1 }
{ "_id" : 1236, "count" : 2 }
{ "_id" : 1237, "count" : 3 }
{ "_id" : 1238, "count" : 3 }
Now I want to count the counts. So the above result would turn into this.
{ "_id" : 1, "count" : 2 }
{ "_id" : 2, "count" : 1 }
{ "_id" : 3, "count" : 2 }
Is this possible to do with a query, or do I need to write some code to get this done?
I updated the query to have another "step" that counts the counts. This is how it looks.
db.collection.aggregate([
{
$group : {
_id : "$propertyId",
count: { $sum: 1 }
}
},
{
$group : {
_id : "$count",
countOfCounts: { $sum: 1 }
}
},
{
$sort : { countOfCounts: 1 }
}
],
{
allowDiskUse:true
});

How to count occurences of values in a nested array?

I've searched but could not find an answer to my problem. I need to count the occurences of the field "nationalCode". I've got a collection with this sample structure in MongoDB:
{
"_id" : ObjectId("5d7519cc6c17d65d4983f048"),
"origin" : "Base1",
"topic" : [
{
"nationalTopic" : {
"nationalCode" : 26
},
"dateTime" : NumberLong(20120927000000)
},
{
"nationalTopic" : {
"nationalCode" : 132
},
"dateTime" : NumberLong(20120927000000)
},
{
"nationalTopic" : {
"nationalCode" : 26
},
"dateTime" : NumberLong(20120927000000)
},
{
"nationalTopic" : {
"nationalCode" : 26
},
"dateTime" : NumberLong(20121005000000)
}
]
}
I've used the following code (I tried many variations of it, but none of them got me the right results):
db.processos.aggregate(
[
{ "$unwind": "$topic" },
{"$match": {"origin": "Base1"}},
{"$group": { "_id": { nationalCode: "$topic.nationalTopic.nationalCode", "count": { "$sum": 1 }} } }
]
)
I'm expecting something like this:
{
"_id" : {
"nationalCode" : 26,
"count" : 3.0
}
}
/* 2 */
{
"_id" : {
"nationalCode" : 132,
"count" : 1.0
}
}
You should extract the count element from the _id.
The following query worked for me.
db.data.aggregate(
[
{ "$unwind": "$topic" },
{"$match": {"origin": "Base1"}},
{"$group": { _id: { "nationalCode": "$topic.nationalTopic.nationalCode" },
"count": {$sum: 1} }
}
]
)
just do it with $project to change your format
do it like this
MongoDB Enterprise >
db.ggg.aggregate(
[
{$unwind:"$topic"},
{"$match": {"origin": "Base1"}},
{"$group": { "_id": { nationalCode: "$topic.nationalTopic.nationalCode"},
"count": { "$sum": 1 } }},
{$project :{"_id.nationalCode":1,"_id.count":"$count"}}
]
)
here it the result !
{ "_id" : { "nationalCode" : 26, "count" : 3 } }
{ "_id" : { "nationalCode" : 132, "count" : 1 } }

How to Group mongodb - mapReduce output?

i have a query regarding the mapReduce framework in mongodb, so i have a result of key value pair from mapReduce function , now i want to run the query on this output of mapReduce.
So i am using mapReduce to find out the stats of user like this
db.order.mapReduce(function() { emit (this.customer,{count:1,orderDate:this.orderDate.interval_start}) },
function(key,values){
var sum =0 ; var lastOrderDate;
values.forEach(function(value) {
if(value['orderDate']){
lastOrderDate=value['orderDate'];
}
sum+=value['count'];
});
return {count:sum,lastOrderDate:lastOrderDate};
},
{ query:{status:"DELIVERED"},out:"order_total"}).find()
which give me output like this
{ "_id" : ObjectId("5443765ae4b05294c8944d5b"), "value" : { "count" : 1, "orderDate" : ISODate("2014-10-18T18:30:00Z") } }
{ "_id" : ObjectId("54561911e4b07a0a501276af"), "value" : { "count" : 2, "lastOrderDate" : ISODate("2015-03-14T18:30:00Z") } }
{ "_id" : ObjectId("54561b9ce4b07a0a501276b1"), "value" : { "count" : 1, "orderDate" : ISODate("2014-11-01T18:30:00Z") } }
{ "_id" : ObjectId("5458712ee4b07a0a501276c2"), "value" : { "count" : 2, "lastOrderDate" : ISODate("2014-11-03T18:30:00Z") } }
{ "_id" : ObjectId("545f64e7e4b07a0a501276db"), "value" : { "count" : 15, "lastOrderDate" : ISODate("2015-06-04T18:30:00Z") } }
{ "_id" : ObjectId("54690771e4b0070527c657ed"), "value" : { "count" : 6, "lastOrderDate" : ISODate("2015-06-03T18:30:00Z") } }
{ "_id" : ObjectId("54696c64e4b07f3c07010b4a"), "value" : { "count" : 1, "orderDate" : ISODate("2014-11-18T18:30:00Z") } }
{ "_id" : ObjectId("546980d1e4b07f3c07010b4d"), "value" : { "count" : 4, "lastOrderDate" : ISODate("2015-03-24T18:30:00Z") } }
{ "_id" : ObjectId("54699ac4e4b07f3c07010b51"), "value" : { "count" : 30, "lastOrderDate" : ISODate("2015-05-23T18:30:00Z") } }
{ "_id" : ObjectId("54699d0be4b07f3c07010b55"), "value" : { "count" : 1, "orderDate" : ISODate("2014-11-16T18:30:00Z") } }
{ "_id" : ObjectId("5469a1dce4b07f3c07010b59"), "value" : { "count" : 2, "lastOrderDate" : ISODate("2015-04-29T18:30:00Z") } }
{ "_id" : ObjectId("5469a96ce4b07f3c07010b5e"), "value" : { "count" : 1, "orderDate" : ISODate("2014-11-16T18:30:00Z") } }
{ "_id" : ObjectId("5469c1ece4b07f3c07010b64"), "value" : { "count" : 9, "lastOrderDate" : ISODate("2015-04-15T18:30:00Z") } }
{ "_id" : ObjectId("5469f422e4b0ce7d5ee021ad"), "value" : { "count" : 5, "lastOrderDate" : ISODate("2015-06-01T18:30:00Z") } }
......
Now i want to run query and group the users on the basis of count in different categories like for user with count less than 5 in one group , 5-10 in another, etc
and want output something like this
{userLessThan5: 9 }
{user5to10: 2 }
{user10to15: 1 }
{user15to20: 0 }
....
Try this,
db.order.mapReduce(function() { emit (this.customer,{count:1,orderDate:this.orderDate.interval_start}) },
function(key,values){
var category; // add this new field
var sum =0 ; var lastOrderDate;
values.forEach(function(value) {
if(value['orderDate']){
lastOrderDate=value['orderDate'];
}
sum+=value['count'];
});
// at this point you are already aware in which category your records lies , just add a new field to mark it
if(sum < 5){ category: userLessThan5};
if(sum >= 5 && sum <=10){ category: user5to10};
if(sum <= 10 && sum >= 15){ category: user10to15};
if(sum <= 15 && sum >=20){ category: user15to20};
....
return {count:sum,lastOrderDate:lastOrderDate,category:category};
},
{ query:{status:"DELIVERED"},out:"order_total"}).find()
db.order_total.aggregate([{ $group: { "_id": "$value.category", "users": { $sum: 1 } } }]);
you will get you desired result
{userLessThan5: 9 }
{user5to10: 2 }
{user10to15: 1 }
{user15to20: 0 }
....
I wrote a query using your data in aggregation as per my knowledge, there may be better way to solve this problem.
var a=db.test.aggregate([{$match:{"value.count":{$lt:5}}},
{ $group: { _id:"$value.count",total:{"$sum":1}}},
{$group:{_id:"less than 5",total:{$sum:"$total"}}}])
var b=db.test.aggregate([{$match:{"value.count":{$lt:10,$gt:5}}},
{ $group: { _id:"$value.count",total:{"$sum":1}}},
{$group:{_id:"between 5 and 10",total:{$sum:"$total"}}}])
var c=db.test.aggregate([{$match:{"value.count":{$lt:15,$gt:10}}},
{ $group: { _id:"$value.count",total:{"$sum":1}}},
{$group:{_id:"between 10 and 15",total:{$sum:"$total"}}}])
insert a, b, c into another collection
You could try to group the output data after mapreduce to every 5 interval count through aggregate like below
db.data.aggregate([
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$value.count", 0 ] },
{ "$mod": [
{ "$subtract": [ "$value.count", 0 ] },
5
]}
]
},
"count": { "$sum": 1 }
}}
])
Also maybe here is one related question here.

$sum arrays with the same ids in mongodb

The two documents of my collection look like this:
First document
{
"_id" : 2055,
"counervalues" : {
"chcounter" : 3
"bscounter" : 10
}
"attributionvalues" :[
{
"id" : 1
"conversionvalue" : 85.0
"conversioncounter" : 6300.0
},
{
"id" : 2
"conversionvalue" : 25.0
"conversioncounter" : 600
}
}
Second document
{
"_id" : 1046,
"counervalues" : {
"chcounter" : 23
"bscounter" : 46
}
"attributionvalues" :[
{
"id" : 1
"conversionvalue" : 15.0
"conversioncounter" : 275.0
},
{
"id" : 2
"conversionvalue" : 65.0
"conversioncounter" : 12000.0
}
}
Now I want to apply the aggregation framework in order to get a new document which has a result as this:
Result
{
"_id" : 3005,
"counervalues" : {
"chcounter" : 26
"bscounter" : 56
}
"attributionvalues" :[
{
"id" : 1
"conversionvalue" : 100.0
"conversioncounter" : 6575.0
},
{
"id" : 2
"conversionvalue" : 90.0
"conversioncounter" : 12600.0
}
}
I started my aggregation like this:
db.conversion.counters.aggregate({
$match:
{
"_id" : {"$gte" : 1046 , "$lte" : 2055}
}
$group:
{
cvchc: {$sum: "$counervalues.chcounter"}
cvbsc: {$sum: "$counervalues.bscounter"}
}
});
but I have trouble to match the attributionvalues according to their ids and add them.
Anyone has an idea?
Run the following aggregation pipeline, should give you the desired results:
db.conversion.aggregate([
{ "$match": { "_id" : { "$gte" : 1046 , "$lte" : 2055 } } },
{ "$unwind": "$attributionvalues" },
{
"$group": {
"_id": "$attributionvalues.id",
"cvchc": { "$sum": "$counervalues.chcounter" },
"cvbsc": { "$sum": "$counervalues.bscounter" },
"avcv": { "$sum": "$attributionvalues.conversionvalue" },
"avcc": { "$sum": "$attributionvalues.conversioncounter" }
}
},
{
"$group": {
"_id": null,
"chcounter": { "$first": "$cvchc" },
"bscounter" : { "$first": "$cvbsc" },
"attributionvalues": {
"$push": {
"id": "$_id",
"conversionvalue": "$avcv" ,
"conversioncounter": "$avcc"
}
}
}
},
{
"$project": {
"counervalues": {
"chcounter": "$chcounter",
"bscounter": "$bscounter"
},
"attributionvalues": 1
}
}
])

How can I get a running total with mongodb aggregate framework?

I am fairly new to MongoDB and I am playing with the aggregate framework. One of the examples from the documentation shows the following, which returns total number of new user joins per month and lists the month joined:
db.users.aggregate(
[
{ $project : { month_joined : { $month : "$joined" } } } ,
{ $group : { _id : {month_joined:"$month_joined"} , number : { $sum : 1 } } },
{ $sort : { "_id.month_joined" : 1 } }
]
)
The code outputs the following:
{
"_id" : {
"month_joined" : 1
},
"number" : 3
},
{
"_id" : {
"month_joined" : 2
},
"number" : 9
},
{
"_id" : {
"month_joined" : 3
},
"number" : 5
}
Is it possible to also have each object contain the sum of all users that have joined since the start, so I don't have to run over the objects programmatically and calculate it myself?
Example desired output:
{
"_id" : {
"month_joined" : 1
},
"number" : 3,
"total": 3
},
{
"_id" : {
"month_joined" : 2
},
"number" : 9,
"total": 12
},
{
"_id" : {
"month_joined" : 3
},
"number" : 5,
"total": 17
}