MongoQuery to update document using addition - mongodb

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
}

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

How to check a field is increasing continuously or not in MongoDB

I have a DB with about 500K document in MongoDB. My DB has a field number starting from 1 and increasing continuously. After I count total of the document, I realize some documents are missing (last number field is greater than total document, instead of equal). How can I check which document is missing? A document has the form:
{
"_id" : ObjectId("abc"),
"number" : 499661
}
You can try this approach. Consider you have these documents with missing numbers 1 and 4:
{ number: 0 }
{ number: 2 }
{ number: 3 }
{ number: 5 }
{ number: 6 }
To find the two missing numbers, try this aggregation:
db.test.aggregate([
{
$group: {
_id: null,
nums: { $push: "$number" }
}
},
{
$project: {
_id: 0,
missing_numbers: { $setDifference: [ { $range: [ 0, 7 ] }, "$nums" ] }
}
},
])
The output: { "missing_numbers" : [ 1, 4 ] }

MongoDB - Select Count with Group By & Order By

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

Mongodb: find documents with array field that contains more than one SAME specified value

There is three documents in collection test:
// document 1
{
"id": 1,
"score": [3,2,5,4,5]
}
// document 2
{
"id": 2,
"score": [5,5]
}
// document 3
{
"id": 3,
"score": [5,3,3]
}
I want to fetch documents that score field contains [5,5].
query:
db.test.find( {"score": {"$all": [5,5]}} )
will return document 1, 2 and 3, but I only want to fetch document 1 and 2.
How can I do this?
After reading your problem I personally think mongodb not supported yet this kind of query. If any one knows about how to find this using mongo query they defiantly post answers here.
But I think this will possible using mongo forEach method, so below code will match your criteria
db.collectionName.find().forEach(function(myDoc) {
var scoreCounts = {};
var arr = myDoc.score;
for (var i = 0; i < arr.length; i++) {
var num = arr[i];
scoreCounts[num] = scoreCounts[num] ? scoreCounts[num] + 1 : 1;
}
if (scoreCounts[5] >= 2) { //scoreCounts[5] this find occurrence of 5
printjsononeline(myDoc);
}
});
Changed in version 2.6.
The $all is equivalent to an $and operation of the specified values; i.e. the following statement:
{ tags: { $all: [ "ssl" , "security" ] } }
is equivalent to:
{ $and: [ { tags: "ssl" }, { tags: "security" } ] }
I think you need to pass in a nested array -
So try
db.test.find( {"score": {"$all": [[5,5]]}} )
Source
Changed in version 2.6.
When passed an array of a nested array (e.g. [ [ "A" ] ] ), $all can now match documents where the field contains the nested array as an element (e.g. field: [ [ "A" ], ... ]), or the field equals the nested array (e.g. field: [ "A" ]).
http://docs.mongodb.org/manual/reference/operator/query/all/
You can do it with an aggregation. The first step can use an index on { "score" : 1 } but the rest is hard work.
db.test.aggregate([
{ "$match" : { "score" : 5 } },
{ "$unwind" : "$score" },
{ "$match" : { "score" : 5 } },
{ "$group" : { "_id" : "$_id", "sz" : { "$sum" : 1 } } }, // use $first here to include other fields in the results
{ "$match" : { "sz" : { "$gte" : 2 } } }
])

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
}