MongoDB as many things. Most of features and functionality of MongoDB rest on the fact that it’s a document database. When discussing MongoDB data models, queries to MongoDB, and data stored in MongoDB, we use JSON or Javascript Object Notation. This JSON document provides an example that illustrates the type of data MongoDB stores as a single record. Important advantages of this design are that developer team can design data models to support common data access pattern.
For example, a team building a news website can design a model so that the most viewd pages may require only a single query to the database and can do this an elegant way that is fully supported by MongoDB. In this example, we will combine author, tags and coments to enable rendering a news article with a single database query.
In contrast to relational database design, which will requrie sevreal joins across tables, or an ugly means of storing multiple values in a single table fields.
Since MongoDB is not predicated on joining data from multiple tables, it is much easier to distribute, and shard, data across multiple servers. This means, in MongoDB, there a wide variety of options when considering database deployment from many, inexpensive commodity machine to a few, larger or powerful servers. MongoDB natively supports scaling out through sharding features, so in a way that is abstracted away from application logic. So developers can build their application in a way that is agnositc about the deployment model used. Whether a single node, or a few nodes, or hundreds of nodes are used makes no difference from the perspective of the application. In contrast, joins and multiple table transactions are difficult to do in parallel. Your best option is usually scaling up, acquiring increasingly expensive hardware so that your data can be served from a single server. While not ture, joins, multiple data tables are not missed in MongDB database because the schema design capabilities support models that require atomic reads and writes only to individual documents.
In summary, MongDB enables developer to design data models that make senses for their applications. That is, those that efficiently support common data access patterns.
As we’ll see as we move through this course, mongodb is designed to support agile software engineering practices and meet the scalability and performance needs of modern applications.
Overview of Building an App with MongoDB
Installing MongoDB on Mac
download the mongoDB from official web site
unzip and set the environment variables in the .bash_profile
mkdir -p <the path to the place you store data, e.g. /data/db> chmod 777 <the path to the place you store data, e.g. /data/db>
startup the database with the dbpath
1
➜ ~ mongod --dbpath <the path to the place you store data, e.g. /data/db>
Tips You can put it into a script.
startup mongo shell to connect the mongodb server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
➜ ~ mongo MongoDB shell version v3.6.2 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.6.2 Server has startup warnings: 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** WARNING: This server is bound to localhost. 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** Remote systems will be unable to connect to this server. 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** Start the server with --bind_ip <address> to specify which IP 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** addresses it should serve responses from, or with --bind_ip_all to 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** bind to all interfaces. If this behavior is desired, start the 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten] ** server with --bind_ip 127.0.0.1 to disable this warning. 2018-01-22T16:35:49.495+1100 I CONTROL [initandlisten]
or you haven’t startup database server, so use –nodb
MongoDB Enterprise > help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers rs.help() replica set helpers help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce
show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of login memory, 'global' is default use <db_name> set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell
1 2 3 4 5 6 7 8 9
MongoDB Enterprise > show dbs admin 0.000GB config 0.000GB local 0.000GB m101 0.000GB m102 0.000GB pcat 0.000GB test 0.000GB video 0.000GB
1 2 3
MongoDB Enterprise > use video switched to db video MongoDB Enterprise >
➜ hello_world_nodejs node app.js Hello, World ➜ hello_world_nodejs
HTTP on Node.js
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Source: howtonode.org/hello-node
// Load the http module to create an http server. var http = require('http');
// Configure our HTTP server to respond with Hello World to all requests. var server = http.createServer(function (request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.end("Hello World\n"); });
// Listen on port 8000, IP defaults to 127.0.0.1 server.listen(8000);
// Put a friendly message on the terminal console.log("Server running at http://127.0.0.1:8000/");
1 2
➜ hello_world_http node app.js Server running at http://127.0.0.1:8000/
app.use(function(req, res){ res.sendStatus(404); }); var server = app.listen(3000, function() { var port = server.address().port; console.log('Express server listening on port %s.', port); });
});
package.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "name": "all_together_now", "version": "0.1.0", "description": "Using the MongoDB driver together with route handling and templates", "main": "app.js", "dependencies": { "consolidate": "~0.13.1", "express": "~4.13.3", "mongodb": "~2.1.3", "nunjucks": "~2.2.0" }, "author": "Shannon Bradshaw", "license": "0BSD" }
<h1>Movies</h1> {% for movie in movies %} <li><ahref="http://www.imdb.com/title/{{ movie.imdb }}">{{ movie.title }}, {{ movie.year }}</a></li> {% else %} <li>No movies found.</li> {% endfor %}
Use mongorestore to restore the dump into your running mongod. Do this by opening a terminal window (mac) or cmd window (windows) and navigating to the directory so that the dump directory is directly beneath you. Now type:
mongorestore dump
Note you will need to have your path setup correctly to find mongorestore.
Now, using the Mongo shell, perform a find() on the collection called hw1_1 in the database m101. There is one document in this collection. Please provide the value corresponding to the “answer” key (without the surrounding quotes) from the document returned.
Your assignment for this part of the homework is to install the mongodb driver for Node.js and run the test application.To do this, first download the hw1-2.zip from Download Handout link, uncompress and change into the hw1-2 directory:
cd hw1-2
Use mongorestore to restore the dump into your running mongod. Do this by opening a terminal window (mac) or cmd window (windows) and navigating to the directory so that the dump directory is directly beneath you. Now type:
mongorestore dump
Note you will need to have your path setup correctly to find mongorestore.
Then install the dependencies.
npm install
This should create a “node_modules” directory. Now run the application to get the answer to hw1-2:
node app.js
If you have the mongodb driver installed correctly, this will print out the message ‘Answer: ‘ followed by some additional text. Enter that additional text in the box below.
Your assignment for this part of the homework is to install the mongodb driver for Node.js, Express, and other required dependencies and run the test application. This homework is meant to give you practice using the “package.json” file, which will include some of the code that we provide.
To do this, first download the hw1-3.zip from Download Handout link, uncompress and change into the hw1-3 directory:
cd hw1-3
Use mongorestore to restore the dump into your running mongod. Do this by opening a terminal window (mac) or cmd window (windows) and navigating to the directory so that the dump directory is directly beneath you. Now type:
mongorestore dump
Note you will need to have your path setup correctly to find mongorestore.
Then install all the dependencies listed in the ‘package.json’ file. Calling ‘npm install’ with no specific package tells npm to look for ‘package.json’:
npm install
This should create a “node_modules” directory with all the dependencies. Now run the application to get the answer to hw1-3:
node app.js
If you have all the dependencies installed correctly, this will print the message ‘Express server listening on port 3000’. Navigate to ‘localhost:3000’ in a browser and enter the text that is displayed on that page in the text box below.
However, if there an duplicated key ‘tt0084726’, it only inserted first two and stop report errors because we set ordered true, which means the order of items we insert cannot be changed.
➜ video mongorestore --db video movieDetails.bson 2018-01-24T09:22:57.135+1100 checking for collection data in movieDetails.bson 2018-01-24T09:22:57.137+1100 reading metadata for video.movieDetails from movieDetails.metadata.json 2018-01-24T09:22:57.188+1100 restoring video.movieDetails from movieDetails.bson 2018-01-24T09:22:57.254+1100 no indexes to restore 2018-01-24T09:22:57.254+1100 finished restoring video.movieDetails (2295 documents) 2018-01-24T09:22:57.254+1100 done
do not forget the double quote
- nested structure - array, order is a matter
Equality Matches on Arrays
- ON THE ENTIRE ARRAY
- BASED ON ANY ELEMENT
- BASED ON A SPECIFIC ELEMENT
- MORE COMPLEX MATCHES USING OPERATOR (DISCUSSED IN ANOTHER LESSON)
MongoDB Enterprise > db.movieDetails.find( { rated: "PG" }, { title : 1, _id : 0} ) { "title" : "I Am David" } { "title" : "E.T. the Extra-Terrestrial" } { "title" : "Star Wars: Episode IV - A New Hope" } { "title" : "Star Wars: Episode VI - Return of the Jedi" } { "title" : "Star Wars: Episode I - The Phantom Menace" } { "title" : "Star Wars: Episode II - Attack of the Clones" } { "title" : "Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb" } { "title" : "Zathura: A Space Adventure" } { "title" : "The Adventures of Tintin" } { "title" : "The Adventures of Sharkboy and Lavagirl 3-D" } { "title" : "The Adventures of Buckaroo Banzai Across the 8th Dimension" } { "title" : "The Adventures of Rocky & Bullwinkle" } { "title" : "The Truman Show" } { "title" : "Dead Poets Society" } { "title" : "Treasure Planet" } { "title" : "Planet 51" } { "title" : "The Karate Kid" } { "title" : "The Karate Kid, Part II" } { "title" : "Honey I Blew Up the Kid" } { "title" : "Diary of a Wimpy Kid" } Type "it"for more
video mongorestore --db video moviesScratch.bson 2018-01-24T10:16:29.102+1100 checking for collection data in moviesScratch.bson 2018-01-24T10:16:29.103+1100 reading metadata for video.moviesScratch from moviesScratch.metadata.json 2018-01-24T10:16:29.153+1100 restoring video.moviesScratch from moviesScratch.bson 2018-01-24T10:16:29.219+1100 no indexes to restore 2018-01-24T10:16:29.219+1100 finished restoring video.moviesScratch (8 documents) 2018-01-24T10:16:29.219+1100 done
# this one match those records with country UK or revenue greater than 15 in boxoffice db.movieDetails.find({ boxOffice: { country: "UK", revenue: { $gt: 15 } } })
# this one match those records with the whole element with country UK and revenue greater than 15 db.movieDetails.find({ boxOffice: {$elemMatch: { country: "UK", revenue: { $gt: 15 } } } })
db.movieDetails.updateOne({ title: "The Martian" }, { $set: { "awards": { "wins": 8, "nominations": 14, "text": "Nominated for 3 Golden Globes. Another 8 wins & 14 nominations." } } });
/* * Updates are used to correct errors and, over time, keep our data current. * For movie data, much of what's there is static: directors, authors and the * like. Other content such as reviews and ratings will need to be updated as * users take action. We could use $set for this purpose, but that's an error * prone approach. It's too easy to do the arithmetic incorrectly. Instead, we * have a number of operators that support numeric updates of data: * $min, $max, $inc, $mul. Let's look at an example using $inc to update reviews. */
var reviewText1 = [ "The Martian could have been a sad drama film, instead it was a ", "hilarious film with a little bit of drama added to it. The Martian is what ", "everybody wants from a space adventure. Ridley Scott can still make great ", "movies and this is one of his best." ].join() db.movieDetails.updateOne({ title: "The Martian" }, { $push: { reviews: { rating: 4.5, date: ISODate("2016-01-12T09:00:00Z"), reviewer: "Spencer H.", text: reviewText1 } } })
var reviewText2 = [ "i believe its ranked high due to its slogan 'Bring him Home' there is nothi", "ng in the movie, nothing at all ! Story telling for fiction story !" ].join()
var reviewText3 = [ "This is a masterpiece. The ending is quite different from the book - the mo", "vie provides a resolution whilst a book doesn't." ].join()
var reviewText4 = [ "There have been better movies made about space, and there are elements of t", "he film that are borderline amateur, such as weak dialogue, an uneven tone,", " and film cliches." ].join()
var reviewText5 = [ "This novel-adaptation is humorous, intelligent and captivating in all its v", "isual-grandeur. The Martian highlights an impeccable Matt Damon, power-stac", "ked ensemble and Ridley Scott's masterful direction, which is back in full ", "form." ].join()
var reviewText6 = [ "A declaration of love for the potato, science and the indestructible will t", "o survive. While it clearly is the Matt Damon show (and he is excellent), t", "he supporting cast may be among the strongest seen on film in the last 10 y", "ears. An engaging, exciting, funny and beautifully filmed adventure thrille", "r no one should miss." ].join()
var reviewText7 = [ "The Martian could have been a sad drama film, instead it was a hilarious fi", "lm with a little bit of drama added to it. The Martian is what everybody wa", "nts from a space adventure. Ridley Scott can still make great movies and th", "is is one of his best." ].join()
// Could do this, but it's probably the wrong semantics. db.movieDetails.updateMany({ rated: null }, { $set: { rated: "UNRATED" } }) // Better to do this. db.movieDetails.updateMany({ rated: null }, { $unset: { rated: "" } }) var detail = { "title": "The Martian", "year": 2015, "rated": "PG-13", "released": ISODate("2015-10-02T04:00:00Z"), "runtime": 144, "countries": [ "USA", "UK" ], "genres": [ "Adventure", "Drama", "Sci-Fi" ], "director": "Ridley Scott", "writers": [ "Drew Goddard", "Andy Weir" ], "actors": [ "Matt Damon", "Jessica Chastain", "Kristen Wiig", "Jeff Daniels" ], "plot": "During a manned mission to Mars, Astronaut Mark Watney is presumed" + " dead after a fierce storm and left behind by his crew. But Watney has" + " survived and finds himself stranded and alone on the hostile planet." + " With only meager supplies, he must draw upon his ingenuity, wit and " + "spirit to subsist and find a way to signal to Earth that he is alive.", "poster": "http://ia.media-imdb.com/images/M/" + "MV5BMTc2MTQ3MDA1Nl5BMl5BanBnXkFtZTgwODA3OTI4NjE@._V1_SX300.jpg", "imdb": { "id": "tt3659388", "rating": 8.2, "votes": 187881 }, "tomato": { "meter": 93, "image": "certified", "rating": 7.9, "reviews": 280, "fresh": 261, "consensus": "Smart, thrilling, and surprisingly funny, The Martian offers" + " a faithful adaptation of the bestselling book that brings out the best " + "in leading man Matt Damon and director Ridley Scott.", "userMeter": 92, "userRating": 4.3, "userReviews": 104999 }, "metacritic": 80, "awards": { "wins": 8, "nominations": 14, "text": "Nominated for 3 Golden Globes. Another 8 wins & 14 nominations." }, "type": "movie" }; db.movieDetails.updateOne({ "imdb.id": detail.imdb.id }, { $set: detail }, { upsert: true }); db.movies.replaceOne({ "imdb": detail.imdb.id }, detail); db.reviews.insertMany([{ rating: 2.5, date: ISODate("2015-10-26T04:00:00Z"), reviewer: "Matthew Samuel", text: "There have been better movies made about space, and there are" + " elements of the film that are borderline amateur, such as weak dialogue," + " an uneven tone, and film cliches." }, { rating: 5, date: ISODate("2015-12-18T09:00:00Z"), reviewer: "Jarrad C", text: "The Martian Review: There are some movies you know going into" + " them that they're going to be great. The Martian was not only great but" + " exceeded all my expectations as well. A return to form from director " + "Ridley Scott (Alien, Blade Runner) who directed last year's abysmal " + "'Exodus: Gods and Kings (which I adeptly gave 1/5 because I was happy that" + " it ended), The Martian soars to the heights of a great space epic. " + "In fact the thing that I loved about the Martian more than Alfonso Curon's" + " 'Gravity' and Christopher Nolan's 'Interstellar' is its optimism." + " Botanist Mark Watney played by an incredible Matt Damon, plays his " + "character to a tee without depressing or alienating viewers. It is " + "through this lens that we see plausible science (well somewhat plausible)" + " succeed and the audience truly root for Mark Watney to be rescued by his" + " Ares III crew creating a palpitating suspense during the rescue launch." + " That aside the supporting cast is impeccable, literally every single" + " character feels important and is given enough screen-time to shine," + " from Jessica Chastain's Commander Lewis to Chitwetel Ejiofer's Vincent" + " Kapoor. Also to be highly commended is the diversity of this cast- where" + " every character is simply just equal- just the way it should be in every film." }, { rating: 3, date: ISODate("2015-12-13T03:00:00Z"), reviewer: "hunterjt13", text: "An astronaut/botanist is stranded on Mars and must rely upon " + "ingenuity to survive. It's hard to divorce my opinions about this film " + "from my opinions of the book, for after the film I thought that they had" + " adapted the book but left out all the good parts. The cut that bleeds " + "most is the final chapter, which gives the whole story a philosophical" + " significance that is both poignant and naively inspiring. Nevertheless," + " what remains is a fine tale of how science, wit, perseverance, and " + "intelligence are greater weapons than anything else. Mark Watney's humor" + " survives in the film, even if the film strips him of his vulgarity, all" + "in the service of obtaining a PG-13 rating (really, we must reexamine " + "why one 'fuck' corrupts thirteen- to seventeen-year-olds so much more than " + "ten, twenty, or 100 'fucks'). Mark Watney's intelligence survives the film" + " version, even if the film's story presents him with fewer obstacles to " + "'science the shit out of,' all in the service of giving director Ridley " + "Scott the opportunity to show beautiful Martian sunsets in the time " + "allowed. That Mark Watney character is quite a survivor. Overall, " + "please watch the film - it's good and it's values are inspiring - but read the book too." }, { rating: 4.5, date: ISODate("2015-12-13T03:00:00Z"), reviewer: "Eugene B", text: "This novel-adaptation is humorous, intelligent and captivating in" + " all its visual-grandeur. The Martian highlights an impeccable Matt Damon," + " power-stacked ensemble and Ridley Scott's masterful direction, which is back in full form." }, { rating: 3.5, date: ISODate("2015-10-10T03:00:00Z"), reviewer: "Kevin M. W", text: "Personable sci-fi flick from Ridley Scott that updates the old " + "Robinson Crusoe stuck on a desert isle (and how he learns to survive) " + "trope. First off, make that a deserted planet. Mars. And the background " + "and the hope this film presents is grounded on is our quest to reach beyond" + " the limits of Earth's gravity (and so it loudly parades that we'll " + "overcome every adversity). Now there's science here but let's not get too" + " excited. The emphasis is interestingly on the personalities involved, " + "interestingly because while the characters are the primary focus of this " + "tale on one hand, on the other hand they are only the flimsiest of " + "constructs with zero time spent 'getting to know them'. We only watch while" + " they react to danger. Who they are or who they might be outside of these" + " situations, we never get to see. This momentary drawback weakens the film, " + "but only by a bit. Its worth a watch, Jessica Chastain and Jeff Daniels " + "leading a deep bench of secondary players." }, { rating: 4.5, date: ISODate("2015-10-13T03:00:00Z"), reviewer: "Drake T", text: "Equal parts fun, smart and thrilling. The Martian is a survival " + "story that doesn't ramp up melodrama but instead chooses to humanize " + "Watney's struggle with entertaining laughs. A love letter from Ridley to " + "fans of the book, it's simply flawless in pacing, dialogue and " + "characterization. The only element missing is visual style, there's " + "nothing iconic to look at that'll let us recall the film in years to come." + " Still it's beautifully directed and perfectly acted, an exciting ride " + "through and through. Most definitely a piece of hard fiction that'll leave" + " a mark for 2015 rivaling the success of genre-similar 'Interstellar' of " + "2014 yet completely different in approach of tone." }, { rating: 4.5, date: ISODate("2015-10-22T00:00:00Z"), reviewer: "Jens S", text: "A declaration of love for the potato, science and the indestructible" + " will to survive. While it clearly is the Matt Damon show (and he is " + "excellent), the supporting cast may be among the strongest seen on film " + "in the last 10 years. An engaging, exciting, funny and beautifully filmed " + "adventure thriller no one should miss." }, { rating: 2.5, date: ISODate("2015-09-17T02:00:00Z"), reviewer: "FiLmCrAzY", text: "This movie has everything, excitement, drama, emotion, humour, " + "strong characters led by Damon but ultimately fails to capture my attention!" }, { rating: 3.5, date: ISODate("2015-09-21T11:00:00Z"), reviewer: "Sanjay R", text: "I really like how this film relied more on story than on action " + "and special effects. Goddard manages to keep the screenplay interesting, " + "and sometimes funny, throughout the entire 2 hours and 14 minutes. One of " + "my pet peeves in movies, however, is an isolated man talking to himself " + "and explaining all of his actions as if he knows he is being watched by an" + " audience and is obligated to amuse them. I know that sounds a bit like " + "saying 'Hey Matt Damon, be less entertaining,' but what I am really saying" + " is that I wish the film's entertainment came from a more natural place. " + "Other than my personal bete noire, the film is very well directed, acted " + "and written. A broad range of moviegoers will enjoy it, I would recommend " + "it to anyone." }, { rating: 3.5, date: ISODate("2015-10-15T11:00:00Z"), reviewer: "Emile T" }, { rating: 3.5, date: ISODate("2015-10-14T11:00:00Z"), reviewer: "Carlos M", text: "With a great 3D that explores very well the red landscapes using " + "mostly a large depth of field, this smart science fiction also knows how " + "to use exposition in its favor and works so well due to its delightful " + "sense of humor and efficient moments of tension when it needs to be tense." }, { rating: 4.5, date: ISODate("2015-10-11T03:00:00Z"), reviewer: "Adriel L", text: "Out-standing!" }, { rating: 3.5, date: ISODate("2015-10-05T03:00:00Z"), reviewer: "Pierluigi P", text: "It doesn't take itself too seriously, which translates in an " + "intelligent, immersive and charming adventure of survival. Untouched by " + "sappiness and thoughtful in execution. A triumph for Mr. Scott." }, { rating: 4, date: ISODate("2015-09-17T03:00:00Z"), reviewer: "Flutie A", text: "Shades of 'Cast Away' & 'Apollo 13'. Really enjoyed it!" }, { rating: 4.5, date: ISODate("2015-10-01T03:00:00Z"), reviewer: "KJ P", text: "Director Ridley Scott has hit the point in his life where it is as " + "unpredictable as the weather, as to how good his films will be. I can " + "gladly say, 'The Martian' is not only his best film in a very long time, " + "but it is also one os 2015's best overall pictures. After presumed dead " + "and left on Mars by his crew, botanist Mark Watney must use his scientific" + " skills to savour/grow food to last him up to four years. Filled with " + "unexpected humour, this film is able to balance a light-hearted tone while" + " digging deep into the emotion when necessary. This film had me chuckling " + "quite a bit, and I give full credit to Drew Goddard d Andy Weir who penned " + "the script. This witty sic-fi rescue mission is also as intense as it needs" + " to be, ramping up to the conclusion. From the visuals to the directing, " + "from the writing to the cinematography, and from the acting to the " + "believability of this film, it really is one of the biggest achievements " + "of the year by far. I was enthralled from start to finish. Although I have " + "to fault the film for ending a bit too abruptly, I can forgive that for " + "being the only true thing to bother me. In the end, 'The Martian' is a " + "damn fine piece of filmmaking. Fantastic!" }, { rating: 4, date: ISODate("2015-11-03T09:00:00Z"), reviewer: "Sheldon C", text: "THE MARTIAN is a success because it presents its sci-fi scenarios " + "with care and plausibility, it keeps the plot simple and moving, and it " + "anchors itself with a strong lead actor in a character who is both " + "relatable and charming, resulting in a film that is accordingly thrilling," + " visually dazzling, and surprisingly funny. Although the narrative itself " + "does not necessarily present anything new - we've seen this scenario " + "before - and the story is quite predictable, Ridley Scott's latest benefits" + " from both a strong script that keeps momentum flowing and an especially " + "nuanced performance by Damon; it carries a much different tone than other " + "recent space dramas and for that, it is justified and comes highly recommended." }, { rating: 5, date: ISODate("2016-01-12T09:00:00Z"), reviewer: "Mike S", text: "At no point in time did I have any doubt this movie would end " + "positively. Humor, ingenuity, and a beautiful adventure sums this film up," + " thanks to Matt Damon's impressive performance. The man's willingness to " + "survive with overall optimism gets him home." }, { rating: 0.5, date: ISODate("2016-01-12T07:00:00Z"), reviewer: "Yabo A.", text: "i believe its ranked high due to its slogan 'Bring him Home' there " + "is nothing in the movie, nothing at all ! Story telling for fiction story !" }, { rating: 5, date: ISODate("2016-01-12T09:00:00Z"), reviewer: "Kristina Z.", text: "This is a masterpiece. The ending is quite different from the book " + "- the movie provides a resolution whilst a book doesn't." }, { rating: 4.5, date: ISODate("2016-01-12T09:00:00Z"), reviewer: "Spencer H.", text: "The Martian could have been a sad drama film, instead it was a " + "hilarious film with a little bit of drama added to it. The Martian is " + "what everybody wants from a space adventure. Ridley Scott can still make " + "great movies and this is one of his best." }])
Homework 2.1
Which of the choices below is the title of a movie from the year 2013 that is rated PG-13 and won no awards? Please query the video.movieDetails collection to find the answer.
NOTE: There is a dump of the video database included in the handouts for the “Creating Documents” lesson. Use that data set to answer this question.
1 2 3
MongoDB Enterprise > db.movieDetails.find({rated:"PG-13", "awards.wins" : 0, year : 2003}, {title : 1, "_id" : 0}).pretty() { "title" : "Ek Aur Ek Gyarah: By Hook or by Crook" } MongoDB Enterprise >
Homework 2.2
Using the video.movieDetails collection, which of the queries below would produce output documents that resemble the following. Check all that apply.
NOTE: We are not asking you to consider specifically which documents would be output from the queries below, but rather what fields the output documents would contain.
1 2 3
{ "title" : "P.S. I Love You" } { "title" : "Love Actually" } { "title" : "Shakespeare in Love" }
db.movieDetails.find({title: “Muppets from Space”}, {title: 1})
The key to answering this question is in understanding how projection works in find() queries. Specifically, we’re looking for queries that include projection documents such as the following.
{title: 1, _id: 0}
Homework 2.3
Using the video.movieDetails collection, how many movies list “Sweden” second in the the list of countries.
NOTE: There is a dump of the video database included in the handouts for the “Creating Documents” lesson. Use that data set to answer this question.
As a follow up to the previous question, how many documents in the video.movieDetails collection list both “Comedy” and “Crime” as genres regardless of how many other genres are listed?
NOTE: There is a dump of the video database included in the handouts for the “Creating Documents” lesson. Use that data set to answer this question.
Suppose you wish to update the value of the “plot” field for one document in our “movieDetails” collection to correct a typo. Which of the following update operators and modifiers would you need to use to do this?
Answer: $set
Challenge Problem : Arrays with Nested Documents
Quiz: Challenge Problem: Arrays with Nested Documents This problem is provided as a supplementary learning opportunity. It is more challenging that the ordinary homework. It is ungraded. We do not ask you submit an answer.
Suppose our movie details documents are structured so that rather than contain an awards field that looks like this:
What query would we use in the Mongo shell to return all movies in the video.movieDetails collection that either won or were nominated for a best picture Oscar? You may assume that an award will appear in the oscars array only if the movie won or was nominated. You will probably want to create a little sample data for yourself in order to work this problem.
HINT: For this question we are looking for the simplest query that will work. This problem has a very straightforward solution, but you will need to extrapolate a little from some of the information presented in the “Reading Documents” lesson.
Challenge Problem: Updating Based on Multiple Criteria
This problem is provided as a supplementary learning opportunity. It is more challenging that the ordinary homework. It is ungraded. We do not ask you submit an answer.
Write an update command that will remove the “tomato.consensus” field for all documents matching the following criteria:
The number of imdb votes is less than 10,000. The year for the movie is between 2010 and 2013 inclusive. The tomato.consensus field is null. How many documents required an update to eliminate a “tomato.consensus” field?
NOTE: There is a dump of the video database included in the handouts for the “Creating Documents” lesson. Use that data set to answer this question.
Answer
You can arrive at the answer here in a couple of different ways, either of which provide some good learning opportunities. The key is realizing that you need to report on the number of documents that actually required an update to remove the tomato.consensus field. You can do this either by ensuring that you filter for only those documents that do not contain a tomato.consensus field or by recognizing that only 13 documents were actually modified by your update.
Using the first approach, you can issue the following command.
➜ ~ mongo localhost/crunchbase MongoDB shell version v3.6.2 connecting to: mongodb://localhost:27017/crunchbase MongoDB server version: 3.6.2 Server has startup warnings: 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** WARNING: This server is bound to localhost. 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** Remote systems will be unable to connect to this server. 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** Start the server with --bind_ip <address> to specify which IP 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** addresses it should serve responses from, or with --bind_ip_all to 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** bind to all interfaces. If this behavior is desired, start the 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] ** server with --bind_ip 127.0.0.1 to disable this warning. 2018-01-29T08:50:47.624+1100 I CONTROL [initandlisten] MongoDB Enterprise > show dbs admin 0.000GB config 0.000GB create_lesson_db 0.000GB crunchbase 0.033GB local 0.000GB m101 0.000GB m102 0.000GB pcat 0.000GB test 0.000GB video 0.001GB MongoDB Enterprise > db crunchbase MongoDB Enterprise > show collections companies MongoDB Enterprise > db.companies.find().count() 18801
cursor.toArray() vs cursor.forEach(function)
toArray returns all documents, and then processes them forEach do the iteration of returning and processing part of documents each time
For the space marked with a TODO comment below, write ONE LINE OF CODE that will cause only the name and number_of_employees fields to be returned in query results. To simplify, please do not assign your projection document to a variable as we did in the lesson. Instead, just type the correct projection document directly into the call to the appropriate method.
var cli = commandLineArgs([ { name: "firstYear", alias: "f", type: Number }, { name: "lastYear", alias: "l", type: Number }, { name: "employees", alias: "e", type: Number } ]); var options = cli.parse() if ( !(("firstYear"in options) && ("lastYear"in options))) { console.log(cli.getUsage({ title: "Usage", description: "The first two options below are required. The rest are optional." })); process.exit(); }
assert.equal(err, null); console.log("Successfully connected to MongoDB."); var query = queryDocument(options); var projection = projectionDocument(options);
var cursor = db.collection('companies').find(query); cursor.project(projection); var numMatches = 0;
var cli = commandLineArgs([ { name: "overview", alias: "o", type: String } ]); var options = cli.parse() if (Object.keys(options).length < 1) { console.log(cli.getUsage({ title: "Usage", description: "You must supply at least one option. See below." })); process.exit(); }
return options; }
1 2 3 4 5 6 7 8
➜ regexOperatorInNodeJSDriver node app.js -o "facebook.*chatting" Successfully connected to MongoDB. { overview: 'facebook.*chatting' } { name: 'VisualSage', founded_year: 2008, overview: '<p>VisualSage produces a <a href="http://www.crunchbase.com/company/facebook" title="Facebook">Facebook</a> desktop application that visualizes and provides functionality for your Facebook network. The application is built upon Microsoft’s new technology WPF. </p>\n\n<p>VisualSage provides easy access to many Facebook’s primary functions, including Facebook notification, message, poke, profile, and photo browsing. The application provides chatting functionality, which allows you to instant communicate with your friends on Facebook. You can also arrange and optimize your network by grouping your friends to subnets.</p>\n\n<p>VisualSage is a software division of Minesage.</p>' } Our query was:{"overview":{"$regex":"facebook.*chatting","$options":"i"}} Matching documents: 1
assert.equal(err, null); console.log("Successfully connected to MongoDB."); var query = queryDocument(options); var projection = projectionDocument(options);
var cursor = db.collection('companies').find(query); cursor.project(projection); var numMatches = 0;
var cli = commandLineArgs([ { name: "firstYear", alias: "f", type: Number }, { name: "lastYear", alias: "l", type: Number }, { name: "employees", alias: "e", type: Number } ]); var options = cli.parse() if ( !(("firstYear"in options) && ("lastYear"in options))) { console.log(cli.getUsage({ title: "Usage", description: "The first two options below are required. The rest are optional." })); process.exit(); }
Twitter Developer Documentation is here: https://dev.twitter.com/overview/documentation
Documentation on the streaming API is here: https://dev.twitter.com/streaming/overview
Documentation on the REST API is here: https://dev.twitter.com/rest/public
To use any of the Twitter APIs you will need access tokens. The simplest means of acquiring access tokens is described here: https://dev.twitter.com/oauth/overview/application-owner-access-tokens
The Twitter API client library for Node.js that I used in the lessons is found here: https://www.npmjs.com/package/twitter
Note that you can place your access tokens in a separate file (.env) and use the following package to load them. https://www.npmjs.com/package/dotenv
The package.json file for this lesson contains the dependencies for the twitter and dotenv packages. See the applications in the handouts for examples of how to use. The documentation for the twitter and nodenv packages provides details on setting up your tokens as environment variables, loading them, and using them to access the twitter API.
Assuming the variable db holds a connection to the school database in the following code snippet.
1 2 3 4
var cursor = db.collection("grades").find({}); cursor.skip(6); cursor.limit(2); cursor.sort({"grade": 1});
Which student’s documents will be returned as part of a subsequent call to toArray()?
Seamus, Bob
Homework: 3.3
This application depends on the companies.json dataset distributed as a handout with the findAndCursorsInNodeJSDriver lesson. You must first import that collection. Please ensure you are working with an unmodified version of the collection before beginning this exercise.
To import a fresh version of the companies.json data, please type the following:
If you have already mongoimported this data you will first need to drop the crunchbase database in the Mongo shell. Do that by typing the following two commands, one at a time, in the Mongo shell:
use crunchbase db.dropDatabase()
The code in the attached handout is complete with the exception of the queryDocument() function. As in the lessons, the queryDocument() function builds an object that will be passed to find() to match a set of documents from the crunchbase.companies collection.
For this assignment, please complete the queryDocument() function as described in the TODO comments you will find in that function.
Once complete, run this application by typing:
node buildingQueryDocuments.js
When you are convinced you have completed the application correctly, please enter the average number of employees per company reported in the output. Enter only the number reported. It should be three numeric digits.
As a check that you have completed the exercise correctly, the total number of unique companies reported by the application should equal 42.
If the grading system does not accept the first solution you enter, please do not make further attempts to have your solution graded without seeking some help in the discussion forum.
console.log(options); var query = { "tag_list": {"$regex": 'social-networking' , "$options": "i"} /* TODO: Complete this statement to match the regular expression "social-networking" */ };
if (("firstYear"in options) && ("lastYear"in options)) { /* TODO: Write one line of code to ensure that if both firstYear and lastYear appear in the options object, we will match documents that have a value for the "founded_year" field of companies documents in the correct range. */ query.founded_year = { "$gte": options.firstYear, "$lte": options.lastYear }; } elseif ("firstYear"in options) { query.founded_year = { "$gte": options.firstYear }; } elseif ("lastYear"in options) { query.founded_year = { "$lte": options.lastYear }; }
if ("city"in options) { /* TODO: Write one line of code to ensure that we do an equality match on the "offices.city" field. The "offices" field stores an array in which each element is a nested document containing fields that describe a corporate office. Each office document contains a "city" field. A company may have multiple corporate offices. */ // {"offices.city": "Menlo Park"} query["offices.city"] = options.city } return query; }
functionreport(options) { var totalEmployees = 0; for (key in companiesSeen) { totalEmployees = totalEmployees + companiesSeen[key].number_of_employees; }
var companiesList = Object.keys(companiesSeen).sort(); console.log("Companies found: " + companiesList); console.log("Total employees in companies identified: " + totalEmployees); console.log("Total unique companies: " + companiesList.length); console.log("Average number of employees per company: " + Math.floor(totalEmployees / companiesList.length)); }
Homework: 3.4
In completing this exercise, you will find the “Logical Operators” lesson from Chapter 2 of this course helpful as a refresher on the $or operator.
This application depends on the companies.json dataset distributed as a handout with the “find() and Cursors in the Node.js Driver” lesson. You must first import that collection. Please ensure you are working with an unmodified version of the collection before beginning this exercise.
To import a fresh version of the companies.json data, please type the following:
If you have already mongoimported this data you will first need to drop the crunchbase database in the Mongo shell. Do that by typing the following two commands, one at a time, in the Mongo shell:
use crunchbase
db.dropDatabase()
The code attached is complete with the exception of the queryDocument() function. As in the lessons, the queryDocument() function builds an object that will be passed to find() to match a set of documents from the crunchbase.companies collection.
For this assignment, please complete the queryDocument() function as described in the TODO comments you will find in that function.
Once complete, run this application by typing:
node overviewOrTags.js
When you are convinced you have completed the application correctly, please enter the average number of employees per company reported in the output. Enter only the number reported. It should be two numeric digits.
As a check that you have completed the exercise correctly, the total number of unique companies reported by the application should equal 194.
If the grading system does not accept the first solution you enter, please do not make further attempts to have your solution graded without seeking some help in the discussion forum.
if ("overview"in options) { /* TODO: Write an assignment statement to ensure that if "overview" appears in the options object, we will match documents that have the value of options.overview in either the "overview" field or "tag_list" field of companies documents. You will need to use the $or operator to do this. As a hint, "$or" should be the name of the field you create in the query object. As with the example for options.milestones below, please ensure your regular expression matches are case insensitive. I urge you to test your query in the Mongo shell first and adapt it to fit the syntax for constructing query documents in this application. */ query["$or"] = [ {"overview": {"$regex": options.overview, "$options": "i"}}, { "tag_list": {"$regex": options.overview, "$options": "i"}} ] }
functionreport(options) { var totalEmployees = 0; for (key in companiesSeen) { totalEmployees = totalEmployees + companiesSeen[key].number_of_employees; }
var companiesList = Object.keys(companiesSeen).sort(); console.log("Companies found: " + companiesList); console.log("Total employees in companies identified: " + totalEmployees); console.log("Total unique companies: " + companiesList.length); console.log("Average number of employees per company: " + Math.floor(totalEmployees / companiesList.length)); }
Week 4: Schema Design
MongoDB Schema Design
Application Driven Schema
Relational database schema design conforms 3rd normal. In mongodb, it could be different. There are some problems we should think about such as which data is used together and not read or written all the time.
The key is to get the data access pattern
When design mongodb schema, these things should be known,
rich documents
pre jon/embed data
no mongo joins
no constraints
atomic operation
no declared schema
Quiz
What’s the single most important factor in designing your application schema within MongoDB?
making the design extensible
making it easy to read by a human
✔︎matching the data access patterns ofyour application
keeping the data in third normal form
Relational Normalization
This diagram depicts a database design violates 3rd normalization.
Goals of Nomalization
free the database of modification anomalies (will avoid it in MongoDB)
minimize redesign when extending (very flexiable in MongoDB, can add attributes and values without changing existing the database)
avoid bias toward any particular access pattern (not be worried about in MongoDB)
Given the document schema that we proposed for the blog, how many collections would need to be accessed to display a blog post with its comments and tags?
1
Answer
One document is all that is needed
That’s not to say that you couldn’t break it up into multiple documents, or that there are no advantages in doing so in some circumstances, but there will also be disadvantages; we’ll be talking about this more in other lessons on schema design and data modeling. But only one document is needed.
Living Without Constraints
In traditional relational database design we use foreign key constrain to make sure data consistent when data is updated.
In Mongodb,we don’t have foreign key constraints and use embeding document to do the same thing. We call it pre-join.
Quiz
What does Living Without Constraints refer to?
Keeping your data consistent even though MongoDB lacks foreign key constraints
Living Without Transactions
MongoDB only supports atomic operations. It relies on the pre-join features.
restructure to only a single document
implement lock, critical section, test set
tolerate, which means accepting someone gets the information several seconds earlier than others
Which of the following operations operate atomically within a single document? Check all that apply.
* comparison If separated, there will be inconsistency(atomic operation) if you are not careful. If embeded, there will be working set problem because it may be vary large.
* when designed, consider:
1. the size of the document (>16MB) or the future growth of size
2. consistency
3. convenience
**Quiz**
What's a good reason you might want to keep two documents that are related to each other one-to-one in separate collections? Check all that apply.
- To enforce foreign key constraints - Because the combined size of the documents would be larger than 16MB
Please remember MongoDB hasn't foreign key.
**Lecture Notes **
Read this note after you watch the video. It's also worth noting that you might decide to keep the resume separate from the employee document if the resume needs to exist when no employee exists for that resume. That is, perhaps you first get a resume and they later become an employee, or not.
1 :1 embed 1 : Many embed (from the many to the one) many : many links objectid in the array
Homework: 4.1
Please review the data model for the Crunchbase companies data set. The document from this collection for Facebook is attached in the handout for convenience. Documents in this collection contain several array fields including one for “milestones”.
Suppose we are building a web site that will display companies data in several different views. Based on the lessons in this module and ignoring other concerns, which of the following conditions favor embedding milestones (as they are in the facebook.json example) over maintaining milestones in a separate collection. Check all that apply.
Note: Schema design is as much an art as a science. If you get the answer wrong on your first attempt. Please visit the forum to discuss with your fellow students.
✔︎The number of milestones for a company rarely exceeds 10 per year
Milestones will never contain more than 15 fields
An individual milestone entry will always be smaller than 16K bytes
✔︎One frequently displayed view of our data displays company details such as the “name”, “founded_year”, “twitter_username”, etc. as well as milestones.
Some of the milestone fields such as “stoneable_type” and “stoneable” are frequently the same from one milestone to anpther.
I haven’t got the correct answer, but the principle to support embeding should be the milestones has to be small and viewd often.
Homework: 4.2
Suppose you are working with a set of categories defined using the following tree structure. “Science” is a sub-category of “Books”; “Chemistry” and “Physics” are sub-categories of “Science”; and “Classical Mechanics” and “Quantum Mechanics” are sub categories of “Physics”.
For this tree, each node is represented by a document in a collection called categories. What kind of schema will make it possible to find() all descendant documents of a category using a single query.
Suppose you are working with a library catalog system containing collections for patrons, publishers, and books. Book documents maintain a field “available” that identifies how many copies are currently available for checkout. There is also a field “checkout” that holds a record of all patrons that are currently borrowing a copy of the book. For example, the document below indicates that the library owns four copies of “Good Book”. Three are currently available for checkout. One has been checked out by patron “33457”.