Combining two mongo results into one output? - mongodb

I am using mongoDB, but I am a complete beginner. I have two different queries where I want to combine them both into one output (I'm hoping the answer is a single query)
Query 1:
db.fin.aggregate([
{ "$match": { "misc.incident_characteristics": { "$not": /Officer Involved Incident/ } } },
{ $group: {
_id: "NonOfficerInvolved",
nInjured: { $avg: "$casualties.n_injured" },
nKilled: { $avg: "$casualties.n_killed" }
}
}
])
Which returns
{ "_id" : "NonOfficerInvolved", "nInjured" : 0.5048153043227224, "nKilled" : 0.24339953718948618 }
Query 2:
db.fin.aggregate([
{ $match: { "misc.incident_characteristics": "Officer Involved Incident" } },
{ $group: {
_id: "OfficerInvolved",
nInjured: { $avg: "$casualties.n_injured" },
nKilled: { $avg: "$casualties.n_killed" }
}
}
])
Which returns
{ "_id" : "OfficerInvolved", "nInjured" : 0.3599233845980508, "nKilled" : 0.358965692073686 }
I would like to get the result of both into one table as seen below. Is it possible to do this in one query?
{ "_id" : "NonOfficerInvolved", "nInjured" : 0.5048153043227224, "nKilled" : 0.24339953718948618 }
{ "_id" : "OfficerInvolved", "nInjured" : 0.3599233845980508, "nKilled" : 0.358965692073686 }

Yes, you can definitely do that in one query.
Instead of just matching against the magic string, store the match result in a new field as a boolean or string, then group on that new field.
db.fin.aggregate([
{ "$addFields": { type:{
$cond:[
{$eq:["$misc.incident_characteristics","Officer Involved Incident"]},
"OfficerInvolved",
"NonOfficerInvolved"
]
}}},
{ $group: {
_id: "$type",
nInjured: { $avg: "$casualties.n_injured" },
nKilled: { $avg: "$casualties.n_killed" }
}
}
])
To match using a regular expression, replace the line
{$eq:["$misc.incident_characteristics","Officer Involved Incident"]},
with
{$regexMatch:{
input:"$misc.incident_characteristics",
regex:"Officer Involved Incident"
options:"i"
}},

Related

need me use aggregation mongodb in arrays

I need help in aggregate this query, I need aggregate values of debito
{
"_id" : ObjectId("5a088f6584ccb0a665900726"),
"usuario" : "tamura",
"creditos" : [
{
"nome_do_credito" : "credito inicial",
"credito" : 0
}
],
"debitos" : [
{
"nome_do_debito" : "debito inicial",
"debito" : 0
},
{
"nome_do_debito" : "Faculdade",
"debito" : "150.00"
}
]
}
I need the output
debito : 150
(0+150)
You will first need to turn all your debito fields into a numerical type (as in 150.00) since you cannot do Maths on strings (as in "150.00"). And then the following query should do the trick:
db.collection.aggregate({
$project: {
"debitos": {
$sum: "$debitos.debito"
}
}
})
In case you have more than one document in your collection and you want the total sum over all documents you can run this:
db.collection.aggregate({
$unwind: "$debitos" // flatten the "debitos" array
}, {
$group: {
"_id": null, // do not really group, just throw all documents in the same group
"debitos": {
$sum: "$debitos.debito" // sum up all debito fields
}
}
})

Aggregate is not a function - mongodb/meteor

I have this collection (Spieltag) with two documents in MongoDB:
0: Object Note:2.5 SaisonID:201516 SpielerID:105 SpieltagID:1 Tore:1 _id:"vkD5sMCdZdntoCFGP"
1: Object Note:3 SaisonsID:201516 SpielerID:105 SpieltagID:1 Tore:0 _id:"PrqokMS47K4vx4KR4"
I want to summarize Note (2.5+1) with a "where clause" on SpielerID.
This is what I have tried to use:
Spieltag.aggregate({ $match: {
{ SpielerID: { $gte: 105 } }
} },
{ $group: { _id : null, sum : { $sum: "$Note" } } });
But it doesn't work, throwing Aggregate is not a function. Any idea what's wrong?
First, you need to add the aggregate package for Meteor :
meteor add meteorhacks:aggregate
Second, you must pass an array parameter in aggregate like :
Spieltag.aggregate([{
$match: {
SpielerID: { $gte: 105 },
},
}, {
$group: {
_id: null,
sum: { $sum: '$Note' },
},
}]);

MongoDB: Create Object in Aggregation result

I want to return Object as a field in my Aggregation result similar to the solution in this question. However in the solution mentioned above, the Aggregation results in an Array of Objects with just one item in that array, not a standalone Object. For example, a query like the following with a $push operation
$group:{
_id: "$publisherId",
'values' : { $push:{
newCount: { $sum: "$newField" },
oldCount: { $sum: "$oldField" } }
}
}
returns a result like this
{
"_id" : 2,
"values" : [
{
"newCount" : 100,
"oldCount" : 200
}
]
}
}
not one like this
{
"_id" : 2,
"values" : {
"newCount" : 100,
"oldCount" : 200
}
}
}
The latter is the result that I require. So how do I rewrite the query to get a result like that? Is it possible or is the former result the best I can get?
You don't need the $push operator, just add a final $project pipeline that will create the embedded document. Follow this guideline:
var pipeline = [
{
"$group": {
"_id": "$publisherId",
"newCount": { "$sum": "$newField" },
"oldCount": { "$sum": "$oldField" }
}
},
{
"$project" {
"values": {
"newCount": "$newCount",
"oldCount": "$oldCount"
}
}
}
];
db.collection.aggregate(pipeline);

Return all fields MongoDB Aggregate

I tried searching on here but couldn't really find what I need. I have documents like this:
{
appletype:Granny,
color:Green,
datePicked:2015-01-26,
dateRipe:2015-01-24,
numPicked:3
},
{
appletype:Granny,
color:Green,
datePicked:2015-01-01,
dateRipe:2014-12-28,
numPicked:6
}
I would like to return only those apples picked latest, will all fields. I want my query to return me the first document only essentially. When I try to do:
db.collection.aggregate([
{ $match : { "appletype" : "Granny" } },
{ $sort : { "datePicked" : 1 } },
{ $group : { "_id" : { "appletype" : "$appletype" },
"datePicked" : { $max : "$datePicked" } },
])
It does return me all the apples picked latest, however with only appletype:Granny and datePicked:2015-01-26. I need the remaining fields. I tries using $project and adding all the fields, but it didn't get me what I needed. Also, when I added the other fields to the group, since datePicked is unique, it returned both records.
How can I go about returning all fields, for only the latest datePicked?
Thanks!
From your description, it sounds like you want one document for each of the types of apple in your collection and showing the document with the most recent datePicked value.
Here is an aggregate query for that:
db.collection.aggregate([
{ $sort: { "datePicked": -1 },
{ $group: { _id: "$appletype", color: { $first: "$color" }, datePicked: { $first: "$datePicked" }, dateRipe: { $first: "$dateRipe" }, numPicked: { $first: "$numPicked" } } },
{ $project: { _id: 0, color: 1, datePicked: 1, dateRipe: 1, numPicked: 1, appletype: "$_id" } }
])
But then based on the aggregate query you've written, it looks like you're trying to get this:
db.collection.find({appletype: "Granny"}).sort({datePicked: -1}).limit(1);

MongoDB Aggregation: Counting distinct fields

I am trying to write an aggregation to identify accounts that use multiple payment sources. Typical data would be.
{
account:"abc",
vendor:"amazon",
}
...
{
account:"abc",
vendor:"overstock",
}
Now, I'd like to produce a list of accounts similar to this
{
account:"abc",
vendorCount:2
}
How would I write this in Mongo's aggregation framework
I figured this out by using the $addToSet and $unwind operators.
Mongodb Aggregation count array/set size
db.collection.aggregate([
{
$group: { _id: { account: '$account' }, vendors: { $addToSet: '$vendor'} }
},
{
$unwind:"$vendors"
},
{
$group: { _id: "$_id", vendorCount: { $sum:1} }
}
]);
Hope it helps someone
I think its better if you execute query like following which will avoid unwind
db.t2.insert({_id:1,account:"abc",vendor:"amazon"});
db.t2.insert({_id:2,account:"abc",vendor:"overstock"});
db.t2.aggregate([
{ $group : { _id : { "account" : "$account", "vendor" : "$vendor" }, number : { $sum : 1 } } },
{ $group : { _id : "$_id.account", number : { $sum : 1 } } }
]);
Which will show you following result which is expected.
{ "_id" : "abc", "number" : 2 }
You can use sets
db.test.aggregate([
{$group: {
_id: "$account",
uniqueVendors: {$addToSet: "$vendor"}
}},
{$project: {
_id: 1,
vendorsCount: {$size: "$uniqueVendors"}
}}
]);
I do not see why somebody would have to use $group twice
db.t2.aggregate([ { $group: {"_id":"$account" , "number":{$sum:1}} } ])
This will work perfectly fine.
This approach doesn't make use of $unwind and other extra operations. Plus, this won't affect anything if new things are added into the aggregation. There's a flaw in the accepted answer. If you have other accumulated fields in the $group, it would cause issues in the $unwind stage of the accepted answer.
db.collection.aggregate([{
"$group": {
"_id": "$account",
"vendors": {"$addToSet": "$vendor"}
}
},
{
"$addFields": {
"vendorCount": {
"$size": "$vendors"
}
}
}])
To identify accounts that use multiple payment sources:
Use grouping to count data from multiple account records and group the result by account with count
Use a match case is to filter only such accounts having more than one payment method
db.payment_collection.aggregate([ { $group: {"_id":"$account" ,
"number":{$sum:1}} }, {
"$match": {
"number": { "$gt": 1 }
}
} ])
This will work perfectly fine,
db.UserModule.aggregate(
{ $group : { _id : { "companyauthemail" : "$companyauthemail", "email" : "$email" }, number : { $sum : 1 } } },
{ $group : { _id : "$_id.companyauthemail", number : { $sum : 1 } } }
);
An example
db.collection.distinct("example.item").forEach( function(docs) {
print(docs + "==>>" + db.collection.count({"example.item":docs}))
});