Mongo Basic Drills
by John Vincent
Posted on April 15, 2017
Practice CRUD operations on a Mongo shell.
Basic Mongo Drills.
This article refers to a Thinkful course 2.1.3
Mongo Basic Drills
Getting Started
Download and import data into MongoDB.
For details, see this article
Basics
Start with:
use tempTestDb
db (show current database)
show dbs
show tables
show collections (show tables)
db.getCollectionNames()
Get all
Find the command that retrieves all restaurants.
db['restaurants'].find()
db.restaurants.find()
coll = db.getCollection("restaurants")
coll.find()
coll = db.restaurants
coll.find()
Limit and sort
Find the command that the first 10 restaurants that appear when db.restaurants
is alphabetically sorted by the name property.
db.restaurants.
find().
sort({name: 1}).
limit(10);
Get by _id
Retrieve a single restaurant by _id
from the restaurants collection. This means you'll first need to get the _id
for one of the restaurants imported into the database.
Get the objectid
of the first record and then find the record for that objectid
var objectId = db.restaurants.findOne({}, {_id: 1})._id
db.restaurants.find({_id: objectId});
Verify it is the first record:
db.restaurants.findOne()
Another way to find a record by objectid
var documentId = ObjectId('58f25d86e6f2f6c130af4d9f');
db.restaurants.findOne({_id: documentId});
Get by value
Write a command that gets all restaurants from the borough of "Queens".
db.restaurants.find({borough: "Queens"});
Count these records:
db.restaurants.
find({borough: "Queens"}).count();
5656
ascending order:
db.restaurants.
find({borough: "Queens"}).
sort({name: 1});
descending order:
db.restaurants.
find({borough: "Queens"}).
sort({name: -1});
Limit fields:
db.restaurants.
find({borough: "Queens"}, {borough: 1, name: 1}).
sort({name: 1});
db.restaurants.
find({borough: "Queens"}, {borough: 1, name: 1}).
sort({name: -1});
db.restaurants.
find({}, {borough: 1, name: 1}).
sort({name: -1});
db.restaurants.
find({}, {name: 1, borough: 1}).
sort({name: -1});
db.restaurants.
find({}, {name: 1}).
sort({name: -1});
db.restaurants.
find({}, {name: 1}).
sort({name: 1});
Do not list a column:
db.restaurants.
find({}, {name: 1, _id: 0}).
sort({name: -1});
Exclude columns:
db.restaurants.
find({borough: "Queens"}, {borough: 0, name: 0, address: 0, grades: 0}).
sort({name: -1});
List field in embedded document:
db.restaurants.
find({borough: "Queens"}, {borough: 1, name: 1, "address.street": 1}).
sort({name: -1});
db.restaurants.
find({borough: "Queens"}, {borough: 1, name: 1, "grades.score": 1}).
sort({name: -1});
Ignore empty string:
db.restaurants.
find({name: {$ne:""}}, {name: 1}).
sort({name: 1})
Count
Write a command that gives the number of documents in db.restaurants
db.restaurants.count()
db['restaurants'].count()
=> 25359
db.restaurants.find({name: {$ne:""}}).count()
=> 25208
List the collection and count:
db.getCollectionNames().map(function(name) {
return { "name": name, "count": db[name].count() }
})
Count by nested value
Write a command that gives the number of restaurants whose zip code value is 11206
. Note that this property is at document.address.zipcode
, so you'll need to use dot notation to query on the nested zip code property.
Notice field is in quote "address.zipcode"
db.restaurants.
find({"address.zipcode": {$eq:"11206"}}).count()
155
With this syntax, the equals operator is assumed:
db.restaurants.
find({"address.zipcode": "11206"}).count()
List all records with "address.zipcode" = "11206"
db.restaurants.
find({"address.zipcode": {$eq:"11206"}}, {"address.zipcode": 1})
Delete by id
Write a command that deletes a document from db.restaurants
. This means you'll first need to get the _id
for one of the restaurants imported into the database.
Let's delete the first record with zipcode="11206"
First, get a count of records with zipcode="11206"
db.restaurants.find({"address.zipcode": {$eq:"11206"}}).count()
=> 155
Make objectId
var objectId = db.restaurants.findOne({"address.zipcode": {$eq:"11206"}}, {_id: 1})._id
Ensure it is only one record:
db.restaurants.find({_id: objectId}).count();
=> 1
Delete the record:
db.restaurants.remove({_id: objectId});
Find the record by objectId
to ensure it does not exist:
db.restaurants.find({_id: objectId}).count();
=> 0
Count of records with zipcode="11206"
, should be one less:
db.restaurants.find({"address.zipcode": {$eq:"11206"}}).count()
=> 154
Update a single document
Write a command that sets the name property of a document with a specific _id
to 'Bizz Bar Bang'
. Make sure that you're not replacing the existing document, but instead updating only the name property.
Let's update the first record with zipcode="11206"
var objectId = db.restaurants.findOne({"address.zipcode": {$eq:"11206"}}, {_id: 1})._id
db.restaurants.findOne({_id: objectId});
db.restaurants.updateOne(
{_id: objectId},
{$set: {name: "Foo Bar Bizz Bang"}}
);
db.restaurants.findOne({_id: objectId});
Update many documents
Uh oh, two zip codes are being merged! The '10035' zip code is being merged with '10036'. Write a command that updates values accordingly.
What am I dealing with? Zip Code by NYC Neighborhoods
Zip codes 10035 and 10036 are both in Manhattan.
Check that all these records really are in borough: manhattan
db.restaurants.find( {
$and: [
{"address.zipcode": { $eq: "10035" } },
{"borough": { $eq: "Manhattan"} }
]
}).count()
=> 87
db.restaurants.find( {
$and: [
{"address.zipcode": { $eq: "10035" } },
{"borough": { $ne: "Manhattan"} }
]
}).count()
=> 0
db.restaurants.find( {
$and: [
{"address.zipcode": { $eq: "10036" } },
{"borough": { $eq: "Manhattan"} }
]
}).count()
=> 610
db.restaurants.find( {
$and: [
{"address.zipcode": { $eq: "10036" } },
{"borough": { $ne: "Manhattan"} }
]
}).count()
=> 1
One trouble record, let's see it:
db.restaurants.find( {
$and: [
{"address.zipcode": { $eq: "10036" } },
{"borough": { $ne: "Manhattan"} }
]
})
{ "_id" : ObjectId("58f25d87e6f2f6c130afa02a"), "address" : { "building" : "253", "coord" : [ -73.986403, 40.7602027 ], "street" : "W 47Th St", "zipcode" : "10036" }, "borough" : "Missing", "cuisine" : "Chicken", "grades" : [ { "date" : ISODate("2014-09-30T00:00:00Z"), "grade" : "A", "score" : 7 } ], "name" : "Buffalo Wild Wings Grill & Bar", "restaurant_id" : "50005585" }
Notice that borough = "Missing"
Let's fix that:
var objectId = db.restaurants.findOne({
$and: [
{"address.zipcode": { $eq: "10036" } },
{"borough": { $ne: "Manhattan"} }
]
},
{_id: 1})._id
db.restaurants.findOne({_id: objectId});
object id: 58f25d87e6f2f6c130afa02a
db.restaurants.updateOne(
{_id: objectId},
{$set: {borough: "Manhattan"}}
);
db.restaurants.findOne({_id: objectId});
Fixed that. Redo the counts:
db.restaurants.find( {
$and: [
{"address.zipcode": { $eq: "10036" } },
{"borough": { $eq: "Manhattan"} }
]
}).count()
=> 611
db.restaurants.find( {
$and: [
{"address.zipcode": { $eq: "10036" } },
{"borough": { $ne: "Manhattan"} }
]
}).count()
=> 0
Counts of both zip codes:
db.restaurants.
find({"address.zipcode": {$eq:"10035"}}).count()
=> 87
db.restaurants.
find({"address.zipcode": {$eq:"10036"}}).count()
=> 611
As _id
is the unique key for documents within the collection, just updating the zip code will act as a merge.
db.restaurants.updateMany(
{"address.zipcode": {$eq:"10035"}},
{$set: {"address.zipcode": "10036"}}
);
=> { "acknowledged" : true, "matchedCount" : 87, "modifiedCount" : 87 }
Redo counts of both zip codes:
db.restaurants.
find({"address.zipcode": {$eq:"10035"}}).count()
=> 0
db.restaurants.
find({"address.zipcode": {$eq:"10036"}}).count()
=> 698
Count of 698 records is indeed = 87 + 611