Does mongodb find and update one by one or find all then update all - mongodb

In mongodb, a write operation that updates multiple documents is not atomic.If there are 3 record A,B,C need to be updated.
Does mongodb:
find A, update A, find B, update B, find C, update C
or
find A,B,C and save to memory, forEach, update A,B,C?

Bulk Update is supported in MongoDB.
Please see this example
db.mycollection.find()
{ "_id" : 1, "name" : "A", "designation" : "developer", "company" : "XYZ" }
{ "_id" : 2, "name" : "B", "designation" : "developer", "company" : "XYZ", "expe
rience" : 2 }
{ "_id" : 3, "name" : "C", "designation" : "developer", "company" : "XYZ", "expe
rience" : 3 }
{ "_id" : 4, "name" : "D", "designation" : "developer", "company" : "XYZ", "expe
rience" : 5 }
{ "_id" : 5, "name" : "E", "designation" : "Manager", "company" : "XYZ", "experi
ence" : 10 }
{ "_id" : 6, "name" : "F", "designation" : "Manager", "company" : "XYZ", "experi
ence" : 10 }
{ "_id" : 7, "name" : "G", "designation" : "Manager", "company" : "ABC", "experi
ence" : 10 }
{ "_id" : 8, "name" : "H", "designation" : "Developer", "company" : "ABC", "expe
rience" : 5 }
{ "_id" : 9, "name" : "I", "designation" : "Developer", "company" : "XYZ", "expe
rience" : 5 }
I'm going to do bulk update on mycollection based on the below criteria
XYZ company giving promotion to their members who are developers who
are having an experience of 5 years to senior developer
My commands in Mongo shell are
var bulk = db.mycollection.initializeUnorderedBulkOp();
bulk.find({ $and:[{company:"XYZ"}, {experience:5}] }).update({$set:{designation:"
senior developer", comments:"Congrats you have been promoted to senior developer
"}});
bulk.execute();
Mongo Shell we will get the below result after executing the query
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 2,
"nModified" : 2,
"nRemoved" : 0,
"upserted" : [ ]
})
Two documents where matching our condition of company:"XYZ" and experience:5 and those documents were updated (_id:4, _id:9)
db.mycollection.find()
{ "_id" : 1, "name" : "A", "designation" : "developer", "company" : "XYZ" }
{ "_id" : 2, "name" : "B", "designation" : "developer", "company" : "XYZ", "expe
rience" : 2 }
{ "_id" : 3, "name" : "C", "designation" : "developer", "company" : "XYZ", "expe
rience" : 3 }
{ "_id" : 4, "name" : "D", "designation" : "senior developer", "company" : "XYZ"
, "experience" : 5, "comments" : "Congrats you have been promoted to senior deve
loper" }
{ "_id" : 5, "name" : "E", "designation" : "Manager", "company" : "XYZ", "experi
ence" : 10 }
{ "_id" : 6, "name" : "F", "designation" : "Manager", "company" : "XYZ", "experi
ence" : 10 }
{ "_id" : 7, "name" : "G", "designation" : "Manager", "company" : "ABC", "experi
ence" : 10 }
{ "_id" : 8, "name" : "H", "designation" : "Developer", "company" : "ABC", "expe
rience" : 5 }
{ "_id" : 9, "name" : "I", "designation" : "senior developer", "company" : "XYZ"
, "experience" : 5, "comments" : "Congrats you have been promoted to senior deve
loper" }
Other related interesting References:
What's the difference between findAndModify and update in MongoDB?
https://docs.mongodb.com/manual/reference/method/Bulk.find.update/
https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
https://docs.mongodb.com/v3.2/reference/method/db.collection.findOneAndUpdate/
Hope it Helps!!

Related

Mongodb aggregate match value in array

i'm working with the restaurants db in mongo
{
"_id" : ObjectId("5c66fcf59e184ea712adfba6"),
"address" : {
"building" : "97-22",
"coord" : [
-73.8601152,
40.7311739
],
"street" : "63 Road",
"zipcode" : "11374"
},
"borough" : "Queens",
"cuisine" : "Jewish/Kosher",
"grades" : [
{
"date" : ISODate("2014-11-24T00:00:00.000Z"),
"grade" : "Z",
"score" : 20
},
{
"date" : ISODate("2013-01-17T00:00:00.000Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2012-08-02T00:00:00.000Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2011-12-15T00:00:00.000Z"),
"grade" : "B",
"score" : 25
}
],
"name" : "Tov Kosher Kitchen",
"restaurant_id" : "40356068"
}
I'm tryng to filter with match in aggregate. I want to check if any score in grades is greater than 5
db.runCommand({
aggregate: "restaurants",
pipeline : [
{$match: {"grades": {$anyElementTrue: {"score": {$gt:5}}}}}
but i'm getting this error:
"errmsg" : "unknown operator: $anyElementTrue",
thanks
Try with $eleMatch
db.restaurants.aggregate([{$match: {"grades": {$elemMatch: {"score": {$gt:5}}}}}])

Aggregate distinct values in MongoDB

I have a mongodb db with 18625 collections. It has following keys:
"_id" : ObjectId("5aab14d2fc08b46adb79d99c"),
"game_id" : NumberInt(4),
"score_phrase" : "Great",
"title" : "NHL 13",
"url" : "/games/nhl-13/ps3-128181",
"platform" : "PlayStation 3",
"score" : 8.5,
"genre" : "Sports",
"editors_choice" : "N",
"release_year" : NumberInt(2012),
"release_month" : NumberInt(9),
"release_day" : NumberInt(11)
Now, i wish to create another dimension/ collection with only genres.
If i use the following query :
db.ign.aggregate([ {$project: {"genre":1}}, { $out: "dimen_genre" } ]);
It generates 18625 collections, even though there are only 113 distinct
genres.
How to apply distinct here and get the collection for genres with only the distinct 113 values.
I googled, bt it showed that aggregate and distinct don't work together in mongo.
I also tried : db.dimen_genre.distinct('genre').length
this showed that in dimension_genre, there are 113 distinct genres.
Precisely,
how to make a collection from existing one with only distinct values.
I am really new to NoSQLs.
You can use $addToSet to group unique values in one document and then $unwind to get back multiple docs:
db.ign.aggregate([
{
$group: {
_id: null,
genre: { $addToSet: "$genre" }
}
},
{
$unwind: "$genre"
},
{
$project: {
_id: 0
}
},
{ $out: "dimen_genre" }
]);
You can try
db.names.aggregate(
[
{ $group : { _id : "$genre", books: { $push: "$$ROOT" } } }
]
)
I have tried with Test and Sports as genre
It gives you output something like this
{
"_id" : "Test",
"books" : [
{
"_id" : ObjectId("5aaea6150cc1403ee9a02e0c"),
"game_id" : 4,
"score_phrase" : "Great",
"title" : "NHL 13",
"url" : "/games/nhl-13/ps3-128181",
"platform" : "PlayStation 3",
"score" : 8.5,
"genre" : "Test",
"editors_choice" : "N",
"release_year" : 2012,
"release_month" : 9,
"release_day" : 11
}
]
}
/* 2 */
{
"_id" : "Sports",
"books" : [
{
"_id" : ObjectId("5aaea3be0cc1403ee9a02d97"),
"game_id" : 4,
"score_phrase" : "Great",
"title" : "NHL 13",
"url" : "/games/nhl-13/ps3-128181",
"platform" : "PlayStation 3",
"score" : 8.5,
"genre" : "Sports",
"editors_choice" : "N",
"release_year" : 2012,
"release_month" : 9,
"release_day" : 11
},
{
"_id" : ObjectId("5aaea3c80cc1403ee9a02d9b"),
"game_id" : 4,
"score_phrase" : "Great",
"title" : "NHL 13",
"url" : "/games/nhl-13/ps3-128181",
"platform" : "PlayStation 3",
"score" : 8.5,
"genre" : "Sports",
"editors_choice" : "N",
"release_year" : 2012,
"release_month" : 9,
"release_day" : 11
},
{
"_id" : ObjectId("5aaea3cf0cc1403ee9a02d9f"),
"game_id" : 4,
"score_phrase" : "Great",
"title" : "NHL 13",
"url" : "/games/nhl-13/ps3-128181",
"platform" : "PlayStation 3",
"score" : 8.5,
"genre" : "Sports",
"editors_choice" : "N",
"release_year" : 2012,
"release_month" : 9,
"release_day" : 11
}
]
}

Group by numbers in MongoDB aggregate framework

I am trying to calculate the number of users who are born in particular years using the following pipeline.
{"$group": {"_id": "$birthdayYear", "count": {"$sum": 1}}}
but what I get is the following where all the years are sum, and Mongo does not have a $count function, so what can I do to group the number of users based on the year they're born?
Sample document
{
"_id" : "LrN2tAK4rtyhsYFbr",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1984,
}
/* 1 */
{
"_id" : "birthDayYear",
"count" : 5550.0
}
I have inserted 2 documents into users collections
db.users.insert({ "_id" : "LrN2tAK4rtyhsYFbs", "firstName" : "test", "lastName" : "1", "birthdayDay" : 5, "birthdayMonth" : 8, "birthdayYear" : 1984})
db.users.insert({ "_id" : "LrN2tAK4rtyhsYFbr", "firstName" : "test", "lastName" : "2", "birthdayDay" : 6, "birthdayMonth" : 9, "birthdayYear" : 1984})
And run following query
db.users.aggregate([{$group: {"_id": "$birthdayYear", count: {$sum:1}} }])
And got the result
{ "_id" : 1984, "count" : 2 }
Please check the syntax of your aggregate statement - I believe below shows the desired results:
db.tstso1.aggregate([{$group : {_id : "$birthdayYear", count: { $sum: 1 }}}])
Results:
{ "_id" : 1986, "count" : 2 }
{ "_id" : 1985, "count" : 3 }
{ "_id" : 1984, "count" : 6 }
Documents:
see.pretty();
{
"_id" : "LrN2tAK4rtyhsYFbr",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1984
}
{
"_id" : "2",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1984
}
{
"_id" : "3",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1984
}
{
"_id" : "4",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1984
}
{
"_id" : "6",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1984
}
{
"_id" : "7",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1984
}
{
"_id" : "12",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1985
}
{
"_id" : "13",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1986
}
{
"_id" : "14",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1985
}
{
"_id" : "16",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1986
}
{
"_id" : "17",
"firstName" : "abc",
"lastName" : "",
"birthdayDay" : 5,
"birthdayMonth" : 8,
"birthdayYear" : 1985
}

How to query mongodb with embedded document

Hi i'm practicing mongodb and I'm stuck with a problem. I'av the following set of documents.
{
"_id" : ObjectId("57cf9a134607674792dbad9e"),
"address" : {
"building" : "351",
"coord" : [
-73.9851356,
40.7676919
],
"street" : "West 57 Street",
"zipcode" : "10019"
},
"borough" : "Manhattan",
"cuisine" : "Irish",
"grades" : [
{
"date" : ISODate("2014-09-06T00:00:00.000Z"),
"grade" : "A",
"score" : 2
},
{
"date" : ISODate("2013-07-22T00:00:00.000Z"),
"grade" : "A",
"score" : 11
},
{
"date" : ISODate("2012-07-31T00:00:00.000Z"),
"grade" : "A",
"score" : 12
},
{
"date" : ISODate("2011-12-29T00:00:00.000Z"),
"grade" : "A",
"score" : 12
}
],
"name" : "Dj Reynolds Pub And Restaurant",
"restaurant_id" : "30191841"
}
I want to fetch list of all documents where zipcode is 10019
I'm following mongodb db tutorials and i've tried the following queries but nothing seems to work and i'm getting zero errors.
db.restaurants.find({address:{zipcode:10019}});
db.restaurants.find({"address.zipcode":10019})
zipcode is a string so your query should be
db.restaurants.find({ "address.zipcode": "10019" })
instead of
db.restaurants.find({ "address.zipcode": 10019 })

Get all array subdocuments with a conditional in MongoDB

I have a collection with lot of documents like this:
{
"Items" : [],
"Technicians" : [],
"_id" : ObjectId("537b5ea4c61b1d1743f4341f"),
"budgets" : [
{
"concepts" : [
{
"position" : 0,
"description" : "A",
"price" : "1",
"qty" : "11",
"total" : 11
},
{
"position" : 1,
"description" : "A",
"price" : "2",
"qty" : "22",
"total" : 44
},
{
"position" : 2,
"description" : "A",
"price" : "3",
"qty" : "33",
"total" : 99
},
{
"position" : 3,
"description" : "A",
"price" : "4",
"qty" : "44",
"total" : 176
}
],
"date" : "2014-05-21T10:20:48.696Z",
"id" : 9989,
"status" : "joooder",
"total" : 500
},
{
"id" : 260,
"date" : "2014-05-22T11:12:40.260Z",
"concepts" : [
{
"position" : 0,
"description" : "Nueva",
"price" : "1",
"qty" : "1",
"total" : 1
}
],
"total" : 1,
"status" : "pending"
},
{
"id" : 111,
"date" : "2014-05-22T13:36:28.111Z",
"concepts" : [
{
"position" : 0,
"description" : "Blabla",
"price" : "1",
"qty" : "11",
"total" : 11
}
],
"total" : 11,
"status" : "pending"
}
]
}
Now, I want to get the budgets, but only the budgets if status is quals to pending, but I need to find in all documents of collection.
I tried this:
db.orders.aggregate(
{ $unwind : "$budgets" },
{ $match : {
"budgets.status": "pending"
}});
But this isn't ok...
Edit two:
With this:
db.orders.aggregate(
{ $project : {
budgets : 1
}},
{ $match : {
"budgets.status": "pending"
}});
I get this:
{
"result" : [
{
"_id" : ObjectId("537b5ea4c61b1d1743f4341f"),
"budgets" : [
{
"concepts" : [
{
"position" : 0,
"description" : "A",
"price" : "1",
"qty" : "11",
"total" : 11
},
{
"position" : 1,
"description" : "A",
"price" : "2",
"qty" : "22",
"total" : 44
},
{
"position" : 2,
"description" : "A",
"price" : "3",
"qty" : "33",
"total" : 99
},
{
"position" : 3,
"description" : "A",
"price" : "4",
"qty" : "44",
"total" : 176
}
],
"date" : "2014-05-21T10:20:48.696Z",
"id" : 9989,
"status" : "joooder",
"total" : 500
},
{
"id" : 260,
"date" : "2014-05-22T11:12:40.260Z",
"concepts" : [
{
"position" : 0,
"description" : "Nueva",
"price" : "1",
"qty" : "1",
"total" : 1
}
],
"total" : 1,
"status" : "pending"
},
{
"id" : 111,
"date" : "2014-05-22T13:36:28.111Z",
"concepts" : [
{
"position" : 0,
"description" : "Blabla",
"price" : "1",
"qty" : "11",
"total" : 11
}
],
"total" : 11,
"status" : "pending"
}
]
}
],
"ok" : 1
}
The first status item isn't pending.