MongoDB - Select Count with Group By & Order By - mongodb

I have a SQL Query that I am trying to convert into a MongoDB query.
SELECT `CrimeLSOACode`,
COUNT(`CrimeType`)
AS `value_occurrence`
FROM `Crimes`
WHERE `CrimeType` = "Vehicle crime"
GROUP BY `CrimeType`
ORDER BY `value_occurrence`
DESC LIMIT 1;
The above query should return the CrimeLSOACode field that has the most fields with CrimeType set to = "Vehicle crime".
I have tried using SQL to Mongo mapping charts and converters but cannot figure out how to do similar actions in Mongo without order by.
Any help would be appreciated.
Sample document from collection:
{ "_id" : ObjectId("5cdef63ce59a9d4948e81d6b"),
"CrimeID" : "298620fed5bf614b9adef619aa7aedd24f420f7ce7cafa65f16dde13da371706",
"CrimeMonth" : "2018-05",
"CrimeReportedIn" : "West Yorkshire Police",
"CrimeFallsWithin" : "West Yorkshire Police",
"CrimeLongitude" : NumberDecimal("-1.824938"),
"CrimeLatitude" : NumberDecimal("53.639434"),
"CrimeLocation" : "On or near Bridge Croft", "CrimeLSOACode" : "E01011149",
"CrimeLSOAName" : "Kirklees 045B", "CrimeType" : "Violence and sexual offences",
"CrimeLastOutcomeCategory" : "Under investigation",
"CrimeContext" : "" }

This aggregation will help you
db.crimes.aggregate([
{ $match: { CrimeType: "Violence and sexual offences" } },
{ $group: {
_id: "$CrimeType",
CrimeLSOACode: { $first: "$CrimeLSOACode" },
value_occurrence: { $sum: 1 }
}
},
{ $project: { _id: 0 } },
{ $sort: { value_occurrence: -1 } },
{ $limit: 1 }
])

In SQL you can use in SELECT field only fields, which are grouping or aggregation function(SUM, COUNT, etc.).
According $collection.group
it seems like this:
db.crimes.group(
{
key: { CrimeLSOACode: 1 },
cond: { CrimeType : { $eq: "Vehicle crime" } },
reduce: function( curr, result ) {
result.value_occurrence++;
},
initial: { value_occurrence : 0 }
}
)

Related

select docs where all items in an array match a criteria

Consider this data in mongodb:
{
"ordernumber" : "161288",
"detail" : [
{
"articlenumber" : "1619",
"price" : 10,
},
{
"articlenumber" : "1620",
"price" : 0,
}
]
}
So basic order data with an array of articles in them.
Now I want to query all orders with where ALL items in detail have a price > 0. So the above one is not selected as 1 item has zero.
This errors ($all needs an array):
db.orders.find({'detail.price': { $all: { $gt: 0 }}})
this finds all orders if at least one price > 0.
db.orders.find({'detail.price': { $gt: 0 }})
How is that possible? Select only docs where all items in an array match a criteria?
playground
db.collection.find({
detail: {
$not: {
"$elemMatch": {
price: { //Negate the condition
$lt: 0
}
}
}
}
})
By this way, you can find all the matching docs with the given condition.
To get lt value
db.collection.find({
detail: {
$not: {
"$elemMatch": {
price: {
$gt: 3
}
}
}
}
})
you can do this using with aggregate.
db.orders.aggregate([
{
$unwind:"$detail"
},
{
$match:{
"detail.price":{$gt:0}
}
}
]);

MongoQuery to update document using addition

I have the following document in student collection:
{
"uid": 1,
"eng": 70
}
Now I want to add 10 into eng field and want result 80. to do this I am using following query:
db.getCollection('student').aggregate([{$match:{uid:1}},{$set:{eng:{$sum:10}}}])
but it is not working. SO how can add any number in the field to the required output? is any addition query in MongoDB. help me here
I suggest using the $inc operator here:
db.getCollection('student').update(
{ uid: 1 },
{ $inc: { eng: 10 } }
)
SOLUTION #1: Set sum to the same field eng.
db.student.aggregate([
{ $match: { uid: 1 } },
{
$set: {
eng: { $add: ["$eng", 10] } // $sum: ["$eng", 10] Also works;)
}
}
])
Output:
{
"_id" : ObjectId("6065f94abb72032a689ed61d"),
"uid" : 1,
"eng" : 80
}
SOLUTION #2: Set sum to a different field result.
Using $addFields add result filed.
Using $add add 10 to eng and store it in result.
db.student.aggregate([
{ $match: { uid: 1 } },
{
$addFields: {
result: { $add: ["$eng", 10] }
}
}
])
Output:
{
"_id" : ObjectId("6065f94abb72032a689ed61d"),
"uid" : 1,
"eng" : 70,
"result" : 80
}

Combining two mongo results into one output?

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"
}},

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
}
}
})

MongoDB sum() data

I am new to mongoDB and nosql, what is the syntax to get a sum?
In MySQL, I would do something like this:
SELECT SUM(amount) from my_table WHERE member_id = 61;
How would I convert that to MongoDB? Here is what I have tried:
db.bigdata.aggregate({
$group: {
_id: {
memberId: 61,
total: {$sum: "$amount"}
}
}
})
Using http://docs.mongodb.org/manual/tutorial/aggregation-zip-code-data-set/ for reference you want:
db.bigdata.aggregate(
{
$match: {
memberId: 61
}
},
{
$group: {
_id: "$memberId",
total : { $sum : "$amount" }
}
})
From the MongoDB docs:
The aggregation pipeline is a framework for data aggregation modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into an aggregated results.
It would be better to match first and then group, so that you system only perform group operation on filtered records. If you perform group operation first then system will perform group on all records and then selects the records with memberId=61.
db.bigdata.aggregate(
{ $match : {memberId : 61 } },
{ $group : { _id: "$memberId" , total : { $sum : "$amount" } } }
)
db.bigdata.aggregate(
{ $match : {memberId : 61 } },
{ $group : { _id: "$memberId" , total : { $sum : "$amount" } } }
)
would work if you are summing data which is not a part of array, if you want to sum the data present in some array in a document then use
db.collectionName.aggregate(
{$unwind:"$arrayName"}, //unwinds the array element
{
$group:{_id: "$arrayName.arrayField", //id which you want to see in the result
total: { $sum: "$arrayName.value"}} //the field of array over which you want to sum
})
and will get result like this
{
"result" : [
{
"_id" : "someFieldvalue",
"total" : someValue
},
{
"_id" : "someOtherFieldvalue",
"total" : someValue
}
],
"ok" : 1
}