├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── credits.txt
├── data
├── user.json
├── user2.json
└── zips.json
├── help.txt
├── learnyoumongodb-screenshot.png
├── learnyoumongodb.js
├── menu.json
├── package.json
├── prerequisites.txt
└── problems
├── .DS_Store
├── basics_find_and_modify
├── problem.txt
├── setup.js
└── solution.js
├── basics_indexes
├── problem.txt
├── setup.js
└── solution.js
├── basics_query
├── problem.txt
├── setup.js
└── solution.js
├── basics_update
├── problem.txt
├── setup.js
└── solution.js
├── bulk_insert_with_index_and_query
├── problem.txt
├── setup.js
└── solution.js
├── geospatial_query
├── problem.txt
├── setup.js
└── solution.js
├── hello_world
├── problem.txt
├── setup.js
└── solution.js
├── my_first_insert
├── problem.txt
├── setup.js
└── solution.js
├── my_first_query
├── problem.txt
├── setup.js
└── solution.js
├── retrieving_and_querying_HN_stories
├── problem.txt
├── setup.js
└── solution.js
└── storing_an_image_with_gridfs
├── problem.txt
├── setup.js
└── solution.js
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4 |
5 | If any participant in this project has issues or takes exception with a contribution, they are obligated to provide constructive feedback and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
6 |
7 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
8 |
9 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
10 |
11 | We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, ability or disability, ethnicity, religion, or level of experience.
12 |
13 | ## Credits
14 |
15 | Based on the [Contributor Covenant](https://github.com/Bantik/contributor_covenant) by [Coraline Ada Ehmke (Bantik)](https://github.com/Bantik).
16 |
17 | If you have suggestions to improve this code of conduct, please submit an issue or PR.
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | #Contributing to MongoDBSchool
2 |
3 | We'd love for you to contribute to our source code and to make MongoDBSchool even better than it is today! Here are the guidelines we'd like you to follow:
4 |
5 | - [Code of Conduct](#coc)
6 | - [Question or Problem?](#question)
7 | - [Issues and Bugs](#issue)
8 | - [Feature Requests](#feature)
9 | - [Submission Guidelines](#submit)
10 | - [Further Info](#info)
11 |
12 | ## Code of Conduct
13 | Please read and follow our [Code of Conduct][coc].
14 |
15 | ## Got a Question or Problem?
16 |
17 | If you have questions about how to use MongoDBSchool, please direct these to the [Google Group][groups] discussion list.
18 |
19 | ## Found an Issue?
20 | If you find a bug in the source code or a mistake in the documentation, you can help us by submitting and issue to our [GitHub Repository][github]. Even better you can submit a Pull Request with a fix.
21 |
22 | **Please see the Submission Guidelines below**.
23 |
24 | ## Want a Feature?
25 | You can request a new feature by submitting an issue to our [GitHub Repository][github]. If you would like to implement a new feature then consider what kind of change it is:
26 |
27 | * **Major Changes** that you wish to contribute to the project should be discussed first on our [Google group][groups], to prevent duplication of work, and help you to craft the change so that it is successfully accepted into the
28 | project.
29 | * **Small Changes** can be crafted and submitted to [GitHub Repository][github] as a Pull Request.
30 |
31 |
32 | ## Want a Doc Fix?
33 | If you want to help improve the docs, it's a good idea to let others know what you're working on to minimize duplication of effort. Before starting, check out the issue queue. Comment on an issue to let others know what you're working on, or create a new issue if your work doesn't fit within the scope of any of the existing doc fix projects.
34 |
35 | For large fixes, please build and test the documentation before submitting the PR to be sure you haven't accidentally introduced any layout or formatting issues.You should also make sure that your commit message is labeled "docs:" and follows the **Git Commit Guidelines** outlined below.
36 |
37 | If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly.
38 |
39 | ## Submission Guidelines
40 |
41 | ### Submitting an Issue
42 | Before you submit your issue search the archive, maybe your question was already answered.
43 |
44 | If your issue appears to be a bug, and hasn't been reported, open a new issue.
45 | Help us to maximize the effort we can spend fixing issues and adding new
46 | features, by not reporting duplicate issues. Providing the following information will increase the chances of your issue being dealt with quickly:
47 |
48 | * **Overview of the issue** - if an error is being thrown a non-minified stack trace helps
49 | * **Motivation for or Use Case** - explain why this is a bug for you
50 | * **Angular Version(s)** - is it a regression?
51 | * **Browsers and Operating System** - is this a problem with all browsers or only IE8?
52 | * **Reproduce the error** - provide a live example (using [Plunker][plunker] or
53 | [JSFiddle][jsfiddle]) or a unambiguous set of steps.
54 | * **Related issues** - has a similar issue been reported before?
55 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
56 | causing the problem (line of code or commit)
57 |
58 | **If you get help, help others. Good karma rulez!**
59 |
60 | ### Submitting a Pull Request
61 | Before you submit your pull request consider the following guidelines:
62 |
63 | * Search [GitHub](https://github.com/braz/learnyoumongodb) for an open or closed Pull Request that relates to your submission. You don't want to duplicate effort.
64 | * Make your changes in a new git branch
65 |
66 | ```shell
67 | git checkout -b my-fix-branch master
68 | ```
69 |
70 | * Create your patch, including appropriate test cases.
71 | * Commit your changes and create a descriptive commit message (the
72 | commit message is used to generate release notes:
73 |
74 | ```shell
75 | git commit -a
76 | ```
77 |
78 | * Build your changes locally to ensure all the tests pass
79 |
80 | ```shell
81 | grunt test
82 | ```
83 |
84 | * Push your branch to Github:
85 |
86 | ```shell
87 | git push origin my-fix-branch
88 | ```
89 |
90 | * In Github, send a pull request to `learnyoumongodb:master`.
91 | * If we suggest changes then you can modify your branch, rebase and force a new push to your GitHub
92 | repository to update the Pull Request:
93 |
94 | ```shell
95 | git rebase master -i
96 | git push -f
97 | ```
98 |
99 | That's it! Thank you for your contribution!
100 |
101 | When the patch is reviewed and merged, you can safely delete your branch and pull the changes
102 | from the main (upstream) repository:
103 |
104 | * Delete the remote branch on Github:
105 |
106 | ```shell
107 | git push origin --delete my-fix-branch
108 | ```
109 |
110 | * Check out the master branch:
111 |
112 | ```shell
113 | git checkout master -f
114 | ```
115 |
116 | * Delete the local branch:
117 |
118 | ```shell
119 | git branch -D my-fix-branch
120 | ```
121 |
122 | * Update your master with the latest upstream version:
123 |
124 | ```shell
125 | git pull --ff upstream master
126 | ```
127 |
128 | ## Git Commit Guidelines
129 |
130 | We have very precise rules over how our git commit messages can be formatted. This leads to **more readable messages** that are easy to follow when looking through the **project history**. But also, we use the git commit messages to **generate the MongoDBSchool change log**.
131 |
132 | ### Commit Message Format
133 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special format that includes a **type**, a **scope** and a **subject**:
134 |
135 | ```
136 | ():
137 |
138 |
139 |
140 |
141 | ```
142 |
143 | Any line of the commit message cannot be longer 100 characters! This allows the message to be easier to read on github as well as in various git tools.
144 |
145 | ### Type
146 | Must be one of the following:
147 |
148 | * **feat**: A new feature
149 | * **fix**: A bug fix
150 | * **docs**: Documentation only changes
151 | * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
152 | semi-colons, etc)
153 | * **refactor**: A code change that neither fixes a bug or adds a feature
154 | * **perf**: A code change that improves performance
155 | * **test**: Adding missing tests
156 | * **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
157 | generation
158 |
159 | ### Scope
160 | The scope could be anything specifying place of the commit change. For example `$location`,
161 | `$browser`, `$compile`, `$rootScope`, `ngHref`, `ngClick`, `ngView`, etc...
162 |
163 | ### Subject
164 | The subject contains succinct description of the change:
165 |
166 | * use the imperative, present tense: "change" not "changed" nor "changes"
167 | * don't capitalize first letter
168 | * no dot (.) at the end
169 |
170 | ###Body
171 | Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes"
172 | The body should include the motivation for the change and contrast this with previous behavior.
173 |
174 | ###Footer
175 | The footer should contain any information about **Breaking Changes** and is also the place to
176 | reference GitHub issues that this commit **Closes**.
177 |
178 | ## Further Information
179 | You can find out more detailed information about contributing in the
180 | [MongoDBSchool documentation][contributing].
181 |
182 | [github]: https://github.com/braz/learnyoumongodb
183 | [coc]: https://github.com/braz/learnyoumongodb/blob/master/CODE_OF_CONDUCT.md
184 | [contribute]: https://github.com/braz/learnyoumongodb/blob/master/CONTRIBUTING.md
185 | [contributing]: https://github.com/braz/learnyoumongodb/blob/master/CONTRIBUTING.md
186 | [list]: https://groups.google.com/forum/#!forum/mongodbschool
187 | [groups]: https://groups.google.com/forum/#!forum/mongodbschool
188 | [stackoverflow]: http://stackoverflow.com/questions/tagged/MongoDBSchool
189 | [plunker]: http://plnkr.co/edit
190 | [jsfiddle]: http://jsfiddle.net/
191 | [js-style-guide]: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
192 | [github-pr-helper]: https://chrome.google.com/webstore/detail/github-pr-helper/mokbklfnaddkkbolfldepnkfmanfhpen
193 |
194 | ## Credits
195 |
196 | Based on the [AngularJS Contributing Guide](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).
197 |
198 | If you have suggestions to improve this code of conduct, please submit an issue or PR.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014, Eoin Brazil (the "Original Author")
2 | All rights reserved.
3 |
4 | MIT +no-false-attribs License
5 |
6 | Permission is hereby granted, free of charge, to any person
7 | obtaining a copy of this software and associated documentation
8 | files (the "Software"), to deal in the Software without
9 | restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the
12 | Software is furnished to do so, subject to the following
13 | conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | Distributions of all or part of the Software intended to be used
19 | by the recipients as they would use the unmodified Software,
20 | containing modifications that substantially alter, remove, or
21 | disable functionality of the Software, outside of the documented
22 | configuration mechanisms provided by the Software, shall be
23 | modified such that the Original Author's bug reporting email
24 | addresses and urls are either replaced with the contact information
25 | of the parties responsible for the changes, or removed entirely.
26 |
27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
29 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
31 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
32 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
34 | OTHER DEALINGS IN THE SOFTWARE.
35 |
36 |
37 | Except where noted, this license applies to any and all software
38 | programs and associated documentation files created by the
39 | Original Author, when distributed with the Software.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Learn You The MongoDB For Much Win!
2 |
3 | [](https://bitdeli.com/free "Bitdeli Badge")
4 |
5 | 
6 |
7 |
8 | **An intro to MongoDB via a set of self-guided workshops.**
9 |
10 | 1. Install [Node.js](http://nodejs.org/)
11 | 2. Install [MongoDB](http://mongodb.org/)
12 | 3. Run `sudo npm install braz/learnyoumongodb -g`
13 | 4. Run `learnyoumongodb`
14 | 5. **.. profit!**
15 |
16 | learnyoumongodb
will run through a series of MongoDB workshops. Starting at a basic *"HELLO WORLD"* and moving on to more advanced exercises about dealing with a range of database operations from CRUD to
17 | aggregation using MongoDB.
18 |
19 | ### Contributors
20 |
21 | learnyoumongodb
is proudly brought to you by the following hackers:
22 |
23 |
26 |
27 | You can find out more detailed information about contributing in the
28 | [contribution guide documentation][contributing].
29 |
30 | #### Code of Conduct
31 | Please read and follow our [Code of Conduct][coc].
32 |
33 | ## License
34 | **learnyoumongodb** is Copyright (c) 2014 Eoin Brazil [@braz](https://twitter.com/eoinbrazil) and licenced under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
35 |
36 | **learnyoumongodb** builds on the excellent work by [@rvagg](https://github.com/rvagg) who created **[Workshopper](https://github.com/rvagg/workshopper)** which serves as the original foundation and inspiration for **learnyoumongodb**.
37 |
38 | [contributing]: https://github.com/braz/learnyoumongodb/blob/master/CONTRIBUTING.md
39 | [coc]: https://github.com/braz/learnyoumongodb/blob/master/CODE_OF_CONDUCT.md
--------------------------------------------------------------------------------
/credits.txt:
--------------------------------------------------------------------------------
1 | {yellow}{bold}{appname} is brought to you by the following dedicated hackers:{/bold}{/yellow}
2 |
3 | {bold}Name GitHub Username{/bold}
4 | -----------------------------------
5 | Eoin Brazil @braz
--------------------------------------------------------------------------------
/data/user.json:
--------------------------------------------------------------------------------
1 | [{"firstname":"tony","lastname":"smith","age":35,"username":"tsmith","email":"tsmith@smith.com"}
2 | ,{"firstname":"john","lastname":"ryan","age":18,"username":"ryano","email":"ryano123@hotmail.com"}
3 | ,{"firstname":"paul","lastname":"keogh","age":45,"username":"keoghp","email":"pkeogh@gmail.com"}
4 | ,{"firstname":"frank","lastname":"tarr","age":52,"username":"tarpit","email":"tarpit@software.com"}
5 | ,{"firstname":"sheila","lastname":"jones","age":23,"username":"jones23","email":"sheila@jones.com"}
6 | ,{"firstname":"marie","lastname":"simpson","age":28,"username":"mariesimpson","email":"mairesimpson@hotmail.com"}
7 | ,{"firstname":"sarah","lastname":"leydon","age":19,"username":"sarahl","email":"leydons@gmail.com"}
8 | ,{"firstname":"jane","lastname":"cooper","age":17,"username":"janec","email":"janey3412@gmail.com"}
9 | ,{"firstname":"susan","lastname":"blake","age":25,"username":"sblake","email":"sarah.blake@gmail.com"}
10 | ,{"firstname":"brian","lastname":"blessed","age":55,"username":"vultan","email":"vultan@mongo.com"}
11 | ,{"firstname":"peter","lastname":"comerford","age":38,"username":"peterc","email":"comerford.peter@gmail.com"}
12 | ,{"firstname":"mark","lastname":"lake","age":24,"username":"marklake","email":"m.lake@hotmail.com"}
13 | ,{"firstname":"joan","lastname":"davis","age":47,"username":"jdavis","email":"joan@davis.com"}
14 | ]
--------------------------------------------------------------------------------
/data/user2.json:
--------------------------------------------------------------------------------
1 | [{"firstname":"tony","lastname":"smith","age":35,"username":"tsmith","email":"tsmith@smith.com"}
2 | ,{"firstname":"john","lastname":"ryan","age":18,"username":"ryano","email":"ryano123@hotmail.com"}
3 | ,{"firstname":"paul","lastname":"keogh","age":23,"username":"keoghp","email":"pkeogh@gmail.com"}
4 | ,{"firstname":"frank","lastname":"tarr","age":52,"username":"tarpit","email":"tarpit@software.com"}
5 | ,{"firstname":"sheila","lastname":"jones","age":23,"username":"jones23","email":"sheila@jones.com"}
6 | ,{"firstname":"marie","lastname":"simpson","age":28,"username":"mariesimpson","email":"mairesimpson@hotmail.com"}
7 | ,{"firstname":"sarah","lastname":"leydon","age":31,"username":"sarahl","email":"leydons@gmail.com"}
8 | ,{"firstname":"jane","lastname":"cooper","age":45,"username":"janec","email":"janey3412@gmail.com"}
9 | ,{"firstname":"susan","lastname":"blake","age":25,"username":"sblake","email":"sarah.blake@gmail.com"}
10 | ,{"firstname":"brian","lastname":"blessed","age":55,"username":"vultan","email":"vultan@mongo.com"}
11 | ,{"firstname":"peter","lastname":"comerford","age":38,"username":"peterc","email":"comerford.peter@gmail.com"}
12 | ,{"firstname":"mark","lastname":"lake","age":24,"username":"marklake","email":"m.lake@hotmail.com"}
13 | ,{"firstname":"joan","lastname":"davis","age":47,"username":"jdavis","email":"joan@davis.com"}
14 | ,{"firstname":"sarah","lastname":"ryan","age":37,"username":"ryans","email":"sarahryan@hotmail.com"}
15 | ,{"firstname":"sarah","lastname":"hows","age":24,"username":"hows","email":"shows@gmail.com"}
16 | ,{"firstname":"dominic","lastname":"tarr","age":37,"username":"dtarr","email":"dtarr@thenodefirm.com"}
17 | ,{"firstname":"dominic","lastname":"tarr","age":25,"username":"tarrd","email":"domt@gmail.com"}
18 | ,{"firstname":"jennifer","lastname":"tarr","age":24,"username":"jenny","email":"jenny@hotmail.com"}
19 | ]
--------------------------------------------------------------------------------
/help.txt:
--------------------------------------------------------------------------------
1 | Additional help is available online using the MongoDB docs at:
2 | http://docs.mongodb.org/manual/
3 |
4 | It is recommended that you have taken the basic Node.JS ioschool modules at:
5 | http://nodeschool.io
--------------------------------------------------------------------------------
/learnyoumongodb-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braz/learnyoumongodb/97c05249edb013d69a27bc69ec62787c2b5c7221/learnyoumongodb-screenshot.png
--------------------------------------------------------------------------------
/learnyoumongodb.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const Workshopper = require('workshopper')
4 | , path = require('path')
5 |
6 | Workshopper({
7 | name : 'learnyoumongodb'
8 | , title : 'LEARN YOU THE MONGODB FOR MUCH WIN!'
9 | , appDir : __dirname
10 | , helpFile : path.join(__dirname, 'help.txt')
11 | , prerequisitesFile : path.join(__dirname, 'prerequisites.txt')
12 | , creditsFile : path.join(__dirname, 'credits.txt')
13 | }).init()
--------------------------------------------------------------------------------
/menu.json:
--------------------------------------------------------------------------------
1 | [
2 | "HELLO WORLD"
3 | , "MY FIRST QUERY!"
4 | , "MY FIRST INSERT!"
5 | , "BASICS UPDATE"
6 | , "BASICS QUERY"
7 | , "BASICS INDEXES"
8 | , "BASICS FIND AND MODIFY"
9 | , "BULK INSERT WITH INDEX AND QUERY"
10 | , "GEOSPATIAL QUERY"
11 | , "RETRIEVING AND QUERYING HN STORIES"
12 | , "STORING AN IMAGE WITH GRIDFS"
13 | ]
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learnyoumongodb",
3 | "version": "0.2.4",
4 | "description": "Learn You MongoDB For Much Win! An introduction to MongoDB via a set of self-guided workshops.",
5 | "author": "Eoin Brazil (https://github.com/braz)",
6 | "contributors": [
7 | "Eoin Brazil (https://github.com/braz)"
8 | ],
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/braz/learnyoumongodb.git"
12 | },
13 | "license": "MIT",
14 | "dependencies": {
15 | "workshopper": "~0.6.0",
16 | "through2": "~0.2.1",
17 | "sleep": "~1.1.3",
18 | "request": "~2.33.0"
19 | },
20 | "bin": {
21 | "learnyoumongodb": "./learnyoumongodb.js"
22 | },
23 | "preferGlobal": true,
24 | "bugs": {
25 | "url": "https://github.com/braz/learnyoumongodb/issues"
26 | },
27 | "homepage": "https://github.com/braz/learnyoumongodb",
28 | "main": "learnyoumongodb.js",
29 | "devDependencies": {},
30 | "scripts": {
31 | "test": "echo \"Error: no test specified\" && exit 1"
32 | },
33 | "keywords": [
34 | "workshopper",
35 | "mongodb"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/prerequisites.txt:
--------------------------------------------------------------------------------
1 | {yellow}{bold}Install Node.js and MongoDB, then setup a locally running MongoDB server.{/bold}{/yellow}
2 | ----------------------------------------------------------------------
3 | A running localhost MongoDB server will be required for many of the exercises:.
4 | You will need to install MongoDB and Node to create the environment for this and the following exercises.
5 | - Download MongoDB at: http://mongodb.org/
6 | - Download Node at: http://nodejs.org/
7 | You will need to 'npm install mongodb' to get started with this exercise.
8 | - If you see 'require' in a Node program you may need to install the specific module using npm.
9 |
10 | A useful page on the node.js driver for MongoDB can be found online at:
11 | https://github.com/mongodb/node-mongodb-native
12 |
13 | Read more about setting up MongoDB on your machine at:
14 | http://docs.mongodb.org/manual/installation/
15 |
--------------------------------------------------------------------------------
/problems/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/braz/learnyoumongodb/97c05249edb013d69a27bc69ec62787c2b5c7221/problems/.DS_Store
--------------------------------------------------------------------------------
/problems/basics_find_and_modify/problem.txt:
--------------------------------------------------------------------------------
1 | In this exercise, you will create a NEW database '{bold}mydatabase{/bold}' running on your localhost (127.0.0.1) in port 27017 and you will create a NEW collection '{bold}mycollection{/bold}'.
2 |
3 | You will then insert the following documents (3) into your collection '{bold}mycollection{/bold}' to populate it with some data.
4 |
5 | {blue}{bold}{"name": "Daffy", "animal": "Duck"}{/blue}{/bold}
6 | {blue}{bold}{"name": "Donald", "animal": "Duck"}{/blue}{/bold}
7 | {blue}{bold}{"name": "Howard", "animal": "Duck"}{/blue}{/bold}
8 |
9 | You will then perform a findAndModify operation on the record whose 'name' field that contains the value 'Howard' and set the 'name' field to the value 'Howard the Duck'. The operation should return this modified record to the console.
10 |
11 | Stage 1 - Create the database 'mydatabase' and then create the collection 'mycollection'.
12 |
13 | Stage 2 - Insert the three (3) documents into the collection 'mycollection'.
14 |
15 | Stage 3 - Perform a findAndModify to set the record with a 'name' field of 'Howard' and set the 'name' field to 'Howard the Duck' and return this modified record to the console.
16 |
17 | Your answer to the exercise will be run against the official solution to ensure
18 | that your query returns the correctly modified document.
19 |
20 | This exercise assumes a running MongoDB on your local machine. This means
21 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/'{/yellow}{/bold}. You will create the database and collection you will use for this exercise as part of the exercise.
22 |
23 | ----------------------------------------------------------------------
24 | HINTS:
25 |
26 | In this exercise, you will need to use the `findAndModify()` method with the 'new' option set to 'TRUE' to return the modified document.
27 |
28 | The database API document reference can be found at:
29 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/db.html{/yellow}
30 | and the findAndModify method reference can be found at:
31 | {yellow}http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html{/yellow}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/problems/basics_find_and_modify/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var async = require('async');
3 |
4 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
5 | var collectionname = 'zips';
6 | var MongoClient = require('mongodb').MongoClient
7 | , format = require('util').format;
8 |
9 | async.series([
10 | // Setup for the exercise by ensuring there is no existing data in the 'zips' collection
11 | function(callback) {
12 | MongoClient.connect(server, function(err, db) {
13 | if (err) return callback(err);
14 |
15 | db.dropCollection(collectionname, function(err, result) {
16 | if (err) return callback(err);
17 |
18 | db.close(function(err, result) {
19 | if (err) return callback(err);
20 | }); //db.close
21 | }); //db.dropCollection
22 | }); // MongoClient.connect
23 | callback(null);
24 | } // callback
25 | ],
26 | // callback and error handling
27 | function(err, results) {
28 | if (err) console.warn(err.message);
29 | });
30 |
31 | return { args: [], stdin: null }
32 | }
33 |
--------------------------------------------------------------------------------
/problems/basics_find_and_modify/solution.js:
--------------------------------------------------------------------------------
1 | var server = 'mongodb://127.0.0.1:27017/';
2 | var databasename = 'mydatabase';
3 | var collectionname = 'mycollection';
4 | var MongoClient = require('mongodb').MongoClient
5 | , format = require('util').format;
6 | var async = require('async');
7 | var us = require('underscore');
8 |
9 | // The sleep module and call are used to delay the execution of the solution script to ensure
10 | // it does not check for the existing of the DB created by your program before it has a chance
11 | // to create the database. A lock file or other approach will be used in future.
12 | var sleep = require('sleep');
13 | sleep.sleep(1);
14 |
15 |
16 | MongoClient.connect(server, function(err, db) {
17 | if (err) {
18 | console.warn(err.message);
19 | return;
20 | }
21 | async.series([
22 | // Deterime if the specified database exits
23 | function(callback) {
24 | // Check for the specific database twice then proceed or exit and further checks for collection in the database
25 | db.command({listDatabases: 1 }, function(err, result) {
26 | if (err) callback(err);
27 | var databasedoc = us.find(result.databases, function(doc){ return doc.name == databasename; });
28 |
29 | if (databasedoc != null)
30 | {
31 | db.collectionsInfo(databasedoc.name).toArray(function(err, items) {
32 | if (err) callback(err);
33 |
34 | if (items == null)
35 | {
36 | console.warn("This problem requires you to create a collection called " + collectionname + ".");
37 | db.close();
38 | }
39 | callback(null);
40 | });
41 | }
42 | else
43 | {
44 | db.command({listDatabases: 1 }, function(err, result) {
45 | if (err) callback(err);
46 |
47 | var databasedoc = us.find(result.databases, function(doc){ return doc.name == databasename; });
48 | if (databasedoc != null)
49 | {
50 | db.collectionsInfo(databasedoc.name).toArray(function(err, items) {
51 | if (err) callback(err);
52 |
53 | if (items == null)
54 | {
55 | console.warn("This problem requires you to create a collection called " + collectionname + ".");
56 | db.close();
57 | }
58 | callback(null);
59 | });
60 | }
61 | else
62 | {
63 | console.warn("This problem requires you to create a database called " + databasename + ".");
64 | db.close();
65 | callback(null);
66 | }
67 | });
68 | }
69 | });
70 | callback(null);
71 | },
72 | //
73 | function(callback) {
74 |
75 | var documents_to_insert = [{"name": "Daffy", "animal": "Duck"},{"name": "Donald", "animal": "Duck"},{"name": "Howard", "animal": "Duck"}];
76 | var newDB = db.db(databasename);
77 |
78 | newDB.collection(collectionname).insert(documents_to_insert, {w:1, fsync:true}, function(err, result) {
79 | if (err) return callback(err);
80 |
81 | newDB.collection(collectionname).findAndModify({name:"Howard"}, [['name', 1]], {$set:{name:"Howard the Duck"}}, {new:true, fields: {_id:0}}, function(err, doc) {
82 | if (err) return callback(err);
83 |
84 | if (doc != null)
85 | {
86 | console.log(doc);
87 | }
88 | db.close();
89 | }); // db.findAndModify
90 | }); // db.insert 1
91 |
92 | callback(null);
93 | },
94 | ],
95 | // callback and error handling
96 | function(err, results) {
97 | if (err) console.warn(err.message);
98 | });
99 | }); // connect
100 |
--------------------------------------------------------------------------------
/problems/basics_indexes/problem.txt:
--------------------------------------------------------------------------------
1 | In this exercise, you will use the database '{bold}learnmymongodb{/bold}' running on your localhost (127.0.0.1) on port 27017 for your solution with the collection 'userdetails' being where the user information is stored.
2 |
3 | You will need to create two indexes for this collection, perform three queries using these indexes with the explain() method and output the state (true or false) from MongoDB as to whether its query engine was able to use the specific index to both perform the query and then also to sort the data return within that query.
4 |
5 | The existing documents in the collection 'userdetails' take the following format:
6 |
7 | {blue}{bold}{ "firstname" : "tony",
8 | "lastname" : "smith",
9 | "age" : 35,
10 | "username" : "tsmith",
11 | "email" : "tsmith@smith.com",
12 | "_id" : ObjectId("XXXX")
13 | }{/blue}{/bold}
14 |
15 | Stage 1 - You should add two indexes, the first on the field "age" and the
16 | second on the fields "firstname", "secondname".
17 |
18 | Stage 2 - You should perform three queries in the following order using the
19 | explain() method and printing to the console the value returned in the field
20 | "scanAndOrder" (either true or false).
21 |
22 | i) The first query should query for all users / documents with an age field
23 | value greater than or equal to 25. The query will be written similar to the
24 | "basic_query" problem, however you will need to use the explain() method
25 | parsing the data returned to get the "scanAndOrder" field's value.
26 | ii) The second query should query for documents / users with the age being 35
27 | or less and these results should be sorted by the fields (firstname, secondname) with the explain value of "scanAndOrder" being return to the console.
28 | iii) The third query should query for documents / users with the the firstname
29 | "dominic" and these results should be sorted by fields (firstname, secondname).
30 | The query should print to console the value in the field "scanAndOrder".
31 |
32 | Your answer to the exercise will be run against the official solution to ensure
33 | that your query is targeting the correct age range of users.
34 |
35 | This exercise assumes a running MongoDB on your local machine. This means
36 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/learnmymongodb'{/yellow}{/bold}.
37 | The collection will be {yellow}{bold}'userdetails'{/yellow}{/bold}.
38 |
39 | ----------------------------------------------------------------------
40 | HINTS:
41 |
42 | In this exercise, you will need to use the `collection.find()` with the operator $gte and $lte methods restricting the find to the range of ages specified. Each of the 3 (three) queries will use the explain() method and return to console the value in the field "scanAndOrder". For this exercise, prior to running the queries you will need to have setup 2 (two) indexes, the first index on the field "age" and the second index (compound) on the fields "firstname" and "secondname".
43 |
44 | The createIndex document reference can be found at:
45 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/collection.html#createindex{/yellow}
46 | and the explain method reference can be found at:
47 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/cursor.html#explain{/yellow}
48 |
49 |
50 |
--------------------------------------------------------------------------------
/problems/basics_indexes/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var us = require('underscore');
3 | var async = require('async');
4 | const userdetailsdoc = require('../../data/user2.json');
5 |
6 | // Global definition for variables
7 | var youngest_age;
8 | var oldest_age;
9 | var random_age_in_range;
10 | var random_age_data;
11 |
12 | var server = 'mongodb://127.0.0.1:27017/learnmymongodb';
13 | var collectionname = 'userdetails';
14 | var MongoClient = require('mongodb').MongoClient
15 | , format = require('util').format;
16 | //var query1age = "older_than_or_equal_to_years";
17 |
18 | async.series([
19 | // Taking the earlier data that was stored into global variables, then add it to
20 | // ... the database so we can run the exercise
21 | function(callback) {
22 | MongoClient.connect(server, function(err, db) {
23 | if (err) return callback(err);
24 |
25 | db.createCollection(collectionname, {strict:true}, function(err, collection) {
26 | //if (err) console.warn(err.message); // assume collection exists and log to console, without error it'll be created straight
27 |
28 | db.collection(collectionname).remove( function(err) {
29 | if (err) return callback(err);
30 |
31 | db.collection(collectionname).insert(userdetailsdoc, {w:1, fsync:true}, function(err, result) {
32 | if (err) return callback(err);
33 |
34 | db.close(function(err, result) {
35 | if (err) return callback(err);
36 | }); //db.close
37 | }); // db.insert 1
38 | }); //db.remove
39 | }); //db.createCollection
40 | }); // MongoClient.connect
41 | callback(null);
42 | } // callback
43 | ],
44 | // callback and error handling
45 | function(err, results) {
46 | if (err) console.warn(err.message);
47 | });
48 |
49 | return { args: [], stdin: null }
50 | }
51 |
--------------------------------------------------------------------------------
/problems/basics_indexes/solution.js:
--------------------------------------------------------------------------------
1 | var server = 'mongodb://127.0.0.1:27017/learnmymongodb';
2 | var collectionname = 'userdetails';
3 | var MongoClient = require('mongodb').MongoClient
4 | , format = require('util').format;
5 | var async = require('async');
6 |
7 | MongoClient.connect(server, function(err, db) {
8 | if (err) {
9 | console.warn(err.message);
10 | return;
11 | }
12 |
13 | async.series([
14 | // Deterime if the specified file exits
15 | function(callback) {
16 | var collection = db.collection(collectionname);
17 | collection.createIndex({age:1}, {w:1}, function(err, indexName) {
18 | if (err) callback(err);
19 | });// createIndex 1
20 | collection.createIndex({firstname:1, lastname:1}, {w:1}, function(err, indexName) {
21 | if (err) callback(err);
22 | });// createIndex 2
23 | callback(null);
24 | },
25 | function(callback) {
26 | var collection = db.collection(collectionname);
27 | collection.find({age: { $gte: 25 }}).explain(function(err, explaination) {
28 | if (err) callback(err);
29 | console.log(explaination.scanAndOrder);
30 | }); // first query with explain
31 | callback(null);
32 | },
33 | function(callback) {
34 | var collection = db.collection(collectionname);
35 | collection.find({age: { $lte: 35 }}).sort({firstname:1, secondname:1}).explain(function(err, explaination) {
36 | if (err) callback(err);
37 | console.log(explaination.scanAndOrder);
38 | }); // second query with explain
39 | callback(null);
40 | },
41 | function(callback) {
42 | var collection = db.collection(collectionname);
43 | collection.find({firstname: "dominic"}).sort({firstname:1, secondname:1}).explain(function(err, explaination) {
44 | if (err) callback(err);
45 | console.log(explaination.scanAndOrder);
46 | db.close(function(err, result) {
47 | if (err) callback(err);
48 | }); // end close
49 | }); // third query with explain
50 | callback(null);
51 | }
52 | ],
53 | // callback and error handling
54 | function(err, results) {
55 | if (err) console.warn(err.message);
56 | });
57 | }); // connect
--------------------------------------------------------------------------------
/problems/basics_query/problem.txt:
--------------------------------------------------------------------------------
1 | In this exercise, you will use the database '{bold}learnmymongodb{/bold}'
2 | running on your localhost (127.0.0.1) on port 27017 for your solution with the
3 | collection 'userdetails' being where the user information is stored.
4 |
5 | You will need to count the users / documents which contain an age equal to or
6 | greater than a value specific in another document in the same collection. The
7 | value is specified in the field 'seek_this_age_or_older' and there is one (1)
8 | document in the collection 'userdetails' containing the value with the format:
9 |
10 | {blue}{bold}
11 | { "seek_this_age_or_older" : VALUE_TO_USE_FOR_QUERY, "_id" : ObjectId("XXXX") }
12 | {/blue}{/bold}
13 |
14 | The other documents take the format in the collection 'userdetails':
15 |
16 | {blue}{bold}{ "firstname" : "tony",
17 | "lastname" : "smith",
18 | "age" : 35,
19 | "username" : "tsmith",
20 | "email" : "tsmith@smith.com",
21 | "_id" : ObjectId("XXXX")
22 | }{/blue}{/bold}
23 |
24 | You should count these documents (those containing the field 'age') for
25 | those with an age equal to or greater (older) than the value contained in field
26 | 'seek_this_age_or_older' in the same collection. The result you will need to return
27 | to the console is the **count** or number of documents with this age or greater.
28 |
29 | Your answer to the exercise will be run against the official solution to ensure
30 | that your query is targeting the correct age range of users.
31 |
32 | This exercise assumes a running MongoDB on your local machine. This means
33 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/learnmymongodb'{/yellow}{/bold}.
34 | The collection will be {yellow}{bold}'userdetails'{/yellow}{/bold}.
35 |
36 | ----------------------------------------------------------------------
37 | HINTS:
38 |
39 | In this exercise, you will need to use the `collection.find()` with the operator $gte
40 | method but you will need to restrict the find to the range of ages specified. You will
41 | need to find the value (seek_this_age_or_older) in the collection that specifies
42 | the age range to search.
43 |
44 | The collection document reference can be found at:
45 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/collection.html{/yellow}
46 | and the streaming reference can be found at:
47 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/cursorstream.html{/yellow}
--------------------------------------------------------------------------------
/problems/basics_query/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | const userdetailsdoc = require('../../data/user.json');
3 | var us = require('underscore');
4 | var async = require('async');
5 |
6 | // Global definition for variables
7 | var youngest_age;
8 | var oldest_age;
9 | var random_age_in_range;
10 | var random_age_data;
11 |
12 | var server = 'mongodb://127.0.0.1:27017/learnmymongodb';
13 | var collectionname = 'userdetails';
14 | var MongoClient = require('mongodb').MongoClient
15 | , format = require('util').format;
16 | var seek_this_age_or_older = "older_than_or_equal_to_years";
17 |
18 | async.series([
19 | // Read the file 'userdetails' JSON document and then
20 | // ... get a random age from the available range in the userdetails / results
21 | function(callback) {
22 | var err = null;
23 | youngest_age = us.chain(userdetailsdoc)
24 | .sortBy(function(userdetailsdoc){ return userdetailsdoc.age; })
25 | .map(function(userdetailsdoc){ return userdetailsdoc.age;})
26 | .first()
27 | .value();
28 |
29 | oldest_age = us.chain(userdetailsdoc)
30 | .sortBy(function(userdetailsdoc){ return userdetailsdoc.age; })
31 | .map(function(userdetailsdoc){ return userdetailsdoc.age;})
32 | .last()
33 | .value();
34 |
35 | random_age_in_range = us.random(parseInt(youngest_age), parseInt(oldest_age));
36 | random_age_data = { seek_this_age_or_older : random_age_in_range };
37 | callback(null);
38 | },
39 | // Taking the earlier data that was stored into global variables, then add it to
40 | // ... the database so we can run the exercise
41 | function(callback) {
42 | MongoClient.connect(server, function(err, db) {
43 | if (err) return callback(err);
44 |
45 | db.createCollection(collectionname, {strict:true}, function(err, collection) {
46 | //if (err) console.warn(err.message); // assume collection exists and log to console, without error it'll be created straight
47 |
48 | db.collection(collectionname).remove( function(err) {
49 | if (err) return callback(err);
50 |
51 | db.collection(collectionname).insert(userdetailsdoc, {w:1, fsync:true}, function(err, result) {
52 | if (err) return callback(err);
53 |
54 | db.collection(collectionname).insert(random_age_data, {w:1, fsync:true}, function(err, result) {
55 | if (err) return callback(err);
56 |
57 | db.close(function(err, result) {
58 | if (err) return callback(err);
59 | }); //db.close
60 | }); // db.insert 2
61 | }); // db.insert 1
62 | }); //db.remove
63 | }); //db.createCollection
64 | }); // MongoClient.connect
65 | callback(null);
66 | } // callback
67 | ],
68 | // callback and error handling
69 | function(err, results) {
70 | if (err) console.warn(err.message);
71 | });
72 |
73 | return { args: [], stdin: null }
74 | }
75 |
--------------------------------------------------------------------------------
/problems/basics_query/solution.js:
--------------------------------------------------------------------------------
1 | var server = 'mongodb://127.0.0.1:27017/learnmymongodb';
2 | var collectionname = 'userdetails';
3 | var MongoClient = require('mongodb').MongoClient
4 | , format = require('util').format;
5 |
6 | MongoClient.connect(server, function(err, db) {
7 | if (err) {
8 | console.warn(err.message);
9 | return;
10 | }
11 |
12 | var age_or_greater_to_search_for = {"seek_this_age_or_older" : { $exists: true }};
13 |
14 | var collection = db.collection(collectionname);
15 | collection.find(age_or_greater_to_search_for).toArray( (function(err, item) {
16 | if (err) console.warn(err.message);
17 | query_age_doc = item[0];
18 |
19 | db.collection(collectionname).find({age: { $gte: query_age_doc.seek_this_age_or_older }}).count( function(err, number) {
20 | if (err) console.warn(err.message);
21 | console.log(number);
22 | db.close(function(err, result) {
23 | if (err) console.warn(err.message);
24 | }); // end close
25 | });
26 | }));
27 | }) // connect
--------------------------------------------------------------------------------
/problems/basics_update/problem.txt:
--------------------------------------------------------------------------------
1 | Write a program that opens a MongoDB database '{bold}learnmymongodb{/bold}',
2 | and updates all the entries in the collection '{bold}test2{/bold}' using the
3 | write concern parameter with the update function.
4 |
5 | The existing document/s take the format:
6 |
7 | {blue}{bold}{
8 | "Learning" : "MongoDB"
9 | }{/blue}{/bold}
10 |
11 |
12 | The updated document/s should take the format:
13 |
14 | {blue}{bold}{
15 | "Learning" : "NoSQL with MongoDB"
16 | }{/blue}{/bold}
17 |
18 | Your solution will be verified by the output to the console from your query.
19 |
20 | This exercise assumes a running MongoDB on your local machine. This means
21 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/learnmymongodb'{/yellow}{/bold}.
22 |
23 | ----------------------------------------------------------------------
24 | HINTS:
25 |
26 | {grey}{italic}// Update all the found documents in a collection.{/grey}{/italic}
27 | {blue}{bold}{
28 | collection.update({"Learning":"MongoDB"}, {$set:{"Learning":"NoSQL with MongoDB"}}, {w:1});
29 | });{/blue}{/bold}
30 |
31 | There are a variety of ways to use the update functionality and a good
32 | reference can be found at:
33 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/collection.html{/yellow}
--------------------------------------------------------------------------------
/problems/basics_update/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function (run) {
2 | var server = 'mongodb://127.0.0.1:27017/learnmymongodb';
3 |
4 | var MongoClient = require('mongodb').MongoClient
5 | , format = require('util').format;
6 |
7 | MongoClient.connect(server, function(err, db) {
8 | if (err) {
9 | console.warn(err.message);
10 | return;
11 | }
12 |
13 | db.collection('test2', function(err, collection) {
14 | var stream = collection.find({"Learning" : "NoSQL with MongoDB"}, {"fields": {_id:0}}).stream();
15 | stream.on("data", function(item) {
16 | console.dir(item);
17 | });
18 |
19 | stream.on("end", function() {
20 | db.close(function(err, result) {
21 | if (err) console.warn(err.message);
22 | });
23 | });
24 |
25 | });
26 | });
27 | return {
28 | args : []
29 | , stdin : null
30 | , long : true
31 | }
32 | }
--------------------------------------------------------------------------------
/problems/basics_update/solution.js:
--------------------------------------------------------------------------------
1 | var MongoClient = require('mongodb').MongoClient
2 | , format = require('util').format;
3 |
4 | MongoClient.connect('mongodb://127.0.0.1:27017/learnmymongodb', function(err, db) {
5 | if(err) {
6 | console.warn(err.message);
7 | return;
8 | }
9 |
10 | var olddoc = {"Learning" : "MongoDB"};
11 | var newdoc = {"Learning" : "NoSQL with MongoDB"};
12 |
13 | var collection = db
14 | .collection('test2')
15 | .update(olddoc, {$set: newdoc}, {w:1}, function(err, object) {
16 | if (err) console.warn(err.message);
17 |
18 | db.collection('test2')
19 | .find(newdoc, {"fields": {_id:0}})
20 | .toArray(function(err, object) {
21 | if (err) console.warn(err.message);
22 | console.dir(object);
23 |
24 | db.close(function(err, result) {
25 | if (err) console.warn(err.message);
26 | }); // end close
27 |
28 | }); // end find
29 |
30 | }); // end update
31 |
32 | }); // end connect
33 |
--------------------------------------------------------------------------------
/problems/bulk_insert_with_index_and_query/problem.txt:
--------------------------------------------------------------------------------
1 | In this exercise, you will USE the database '{bold}mydatabase{/bold}' running on your localhost (127.0.0.1) in port 27017 and you will USE the collection '{bold}zips{/bold}'.
2 |
3 | You will load all the records from the 'zips.json' file which is included in the module's data folder or you can download it directly from the MongoDB website (http://media.mongodb.org/zips.json with details at http://docs.mongodb.org/manual/tutorial/aggregation-zip-code-data-set/).
4 |
5 | This file contains 29,469 documents with the following format:
6 | {"city": "ACMAR", "loc": [-86.51557, 33.584132], "pop": 6055, "state": "AL", "_id": "35004"}
7 | ....
8 | {"city": "THAYNE", "loc": [-111.011354, 42.933026], "pop": 505, "state": "WY", "_id": "83127"}
9 |
10 | Stage 1 - Connect to the database, 'mydatabase' and import the file 'zips.json' using the Node MongoDB driver code.
11 |
12 | Stage 2 - You will create a compound index on the fields 'pop', state' and 'city'.
13 |
14 | Stage 3 - You will query the collection to return the cities with a population over one thousand (1,000) people in the state of California or 'CA', these results should be sorted by population, state and city and the result should be outputted to the console.
15 |
16 | Your answer to the exercise will be run against the official solution to ensure
17 | that your query returns the correctly documents.
18 |
19 | This exercise assumes a running MongoDB on your local machine. This means
20 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/'{/yellow}{/bold}.
21 |
22 | ----------------------------------------------------------------------
23 | HINTS:
24 |
25 | In this exercise, you will need to use the bulk insert method rather than the 'mongoimport' commandline tool (http://docs.mongodb.org/manual/reference/program/mongoimport/) as you will need to programmatically report on the total number of records inserted.
26 |
27 | The MongoDB import / export reference can be found at:
28 | {yellow}http://docs.mongodb.org/manual/core/import-export/{/yellow}
29 | and the insert() method reference can be found at:
30 | {yellow}http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html{/yellow}
31 |
--------------------------------------------------------------------------------
/problems/bulk_insert_with_index_and_query/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var async = require('async');
3 |
4 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
5 | var collectionname = 'zips';
6 | var MongoClient = require('mongodb').MongoClient
7 | , format = require('util').format;
8 |
9 | async.series([
10 | // Setup for the exercise by ensuring there is no existing data
11 | function(callback) {
12 | MongoClient.connect(server, function(err, db) {
13 | if (err) return callback(err);
14 |
15 | db.dropCollection(collectionname, function(err, result) {
16 | if (err) return callback(err);
17 | db.close(function(err, result) {
18 | if (err) return callback(err);
19 | }); //db.close
20 | }); //db.dropCollection
21 | }); // MongoClient.connect
22 | callback(null);
23 | } // callback
24 | ],
25 | // callback and error handling
26 | function(err, results) {
27 | if (err) console.warn(err.message);
28 | });
29 |
30 | return { args: [], stdin: null }
31 | }
32 |
--------------------------------------------------------------------------------
/problems/bulk_insert_with_index_and_query/solution.js:
--------------------------------------------------------------------------------
1 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
2 | var databasename = 'mydatabase';
3 | var collectionname = 'zips';
4 | var MongoClient = require('mongodb').MongoClient
5 | , format = require('util').format;
6 | var async = require('async');
7 | var us = require('underscore');
8 |
9 | // The sleep module and call are used to delay the execution of the solution script to ensure
10 | // it does not check for the existing of the DB created by your program before it has a chance
11 | // to create the database. A lock file or other approach will be used in future.
12 | var sleep = require('sleep');
13 | sleep.sleep(1);
14 |
15 | MongoClient.connect(server, function(err, db) {
16 | if (err) {
17 | console.warn(err.message);
18 | return;
19 | }
20 | async.series([
21 | // Deterime if the specified database exits
22 | function(callback) {
23 | var collection = db.collection(collectionname);
24 |
25 | collection.indexInformation(function(err, indexitems) {
26 | if (err) callback(err);
27 |
28 | var index_field_required = ['pop', 'state', 'city'];
29 | var values = us.values(indexitems);
30 | var flattened = us.flatten(values);
31 | var cleaned = us.without(flattened, "_id", 1);
32 | var valid_index = us.intersection(cleaned, index_field_required);
33 |
34 | if (valid_index.length == index_field_required.length) {
35 | collection.find({state: "CA", pop: { $gt: 75000 }}).sort({pop:1, state:1, city:1}).toArray(function(err, result) {
36 | if (err) callback(err);
37 |
38 | console.log(result);
39 | db.close(function(err, result) {
40 | if (err) callback(err);
41 | }); //db.close
42 | }); // first query with explain
43 | callback(null);
44 | }
45 | else {
46 | console.log("This problem requires you to create an index on the collection " + collectionname + " for the fields " + index_key_items.toString() + ".");
47 | db.close(function(err, result) {
48 | if (err) callback(err);
49 | }); //db.close
50 | callback(null);
51 | }
52 | }); // indexInformation()
53 | },
54 | ],
55 | // callback and error handling
56 | function(err, results) {
57 | if (err) console.warn(err.message);
58 | });
59 | }); // connect
60 |
--------------------------------------------------------------------------------
/problems/geospatial_query/problem.txt:
--------------------------------------------------------------------------------
1 | In this exercise, you will USE the database '{bold}mydatabase{/bold}' running on your localhost (127.0.0.1) in port 27017 and you will USE the collection '{bold}zips{/bold}'. This exercise should be done after the exercise "Bulk Insert With Index And Query" as you will load and populate the collection 'zips' as part of that exercise, reusing the data here.
2 |
3 | This zips collection contains 29,469 documents with the following format:
4 | {"city": "ACMAR", "loc": [-86.51557, 33.584132], "pop": 6055, "state": "AL", "_id": "35004"}
5 | ....
6 | {"city": "THAYNE", "loc": [-111.011354, 42.933026], "pop": 505, "state": "WY", "_id": "83127"}
7 |
8 | Stage 1 - Connect to the database, 'mydatabase' and query the collection 'zips' and print the number of records in this collection to the console.
9 |
10 | Stage 2 - You will create a geospatial index of type '2d' on the field 'loc'.
11 |
12 | Stage 3 - Find the cities nearest to the following coordinates in the database. Print the first three records (3) to the console for the cities closest to this location.
13 | {blue}{bold}{"loc" : [ -122.21, 37.78 ]}{/blue}{/bold}
14 |
15 | Your answer to the exercise will be run against the official solution to ensure
16 | that your query returns the correctly documents.
17 |
18 | This exercise assumes a running MongoDB on your local machine. This means
19 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/'{/yellow}{/bold}.
20 |
21 | ----------------------------------------------------------------------
22 | HINTS:
23 |
24 | In this exercise, you will need to use the $near geospatial operator to find all the locations closest to the requested point. It's documentation is:
25 | {yellow}http://docs.mongodb.org/manual/reference/operator/query/near/#op._S_near{/yellow}
26 |
27 | The MongoDB 2D query index reference can be found at:
28 | {yellow}http://docs.mongodb.org/manual/tutorial/query-a-2d-index/{/yellow}
29 |
--------------------------------------------------------------------------------
/problems/geospatial_query/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var us = require('underscore');
3 | var async = require('async');
4 |
5 | var server = 'mongodb://127.0.0.1:27017/';
6 | var databasename = 'mydatabase';
7 | var collectionname = 'zips';
8 | var MongoClient = require('mongodb').MongoClient
9 | , format = require('util').format;
10 |
11 | async.series([
12 | // Setup for the exercise by ensuring there is no existing data
13 | function(callback) {
14 | MongoClient.connect(server, function(err, db) {
15 | if (err) return callback(err);
16 |
17 | // Check for the specific database then proceed or exit and further checks for collection in the database
18 | db.command({listDatabases: 1 }, function(err, result) {
19 | if (err) callback(err);
20 | var databasedoc = us.find(result.databases, function(doc){ return doc.name == databasename; });
21 |
22 | if (databasedoc != null) {
23 | db.collectionsInfo(databasedoc.name).toArray(function(err, items) {
24 | if (err) callback(err);
25 |
26 | if (items == null)
27 | {
28 | var error = new Error("This problem requires you to have loaded the collection called " + collectionname + ". Please refer to the bulk insert exercise for details on where this data comes from and how to import it.");
29 | db.close();
30 | callback(error);
31 | }
32 |
33 | callback(null);
34 | });
35 | }
36 | else {
37 | var error = new Error("This problem requires you to have the database called " + collectionname + " with zips information loaded. Please refer to the bulk insert exercise for details on where this data comes from and how to import it.");
38 | callback(error);
39 | }
40 | }); // db.command({listDatabases: 1 },
41 | }); // MongoClient.connect
42 | callback(null);
43 | } // callback
44 | ],
45 | // callback and error handling
46 | function(err, results) {
47 | if (err) console.warn(err.message);
48 | });
49 |
50 | return { args: [], stdin: null }
51 | }
52 |
--------------------------------------------------------------------------------
/problems/geospatial_query/solution.js:
--------------------------------------------------------------------------------
1 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
2 | var databasename = 'mydatabase';
3 | var collectionname = 'zips';
4 | var MongoClient = require('mongodb').MongoClient
5 | , format = require('util').format;
6 | var async = require('async');
7 | var us = require('underscore');
8 |
9 | // The sleep module and call are used to delay the execution of the solution script to ensure
10 | // it does not check for the existing of the DB created by your program before it has a chance
11 | // to create the database. A lock file or other approach will be used in future.
12 | var sleep = require('sleep');
13 | sleep.sleep(1);
14 |
15 | MongoClient.connect(server, function(err, db) {
16 | if (err) {
17 | console.warn(err.message);
18 | return;
19 | }
20 | async.series([
21 | // Deterime if the specified database exits
22 | function(callback) {
23 | var collection = db.collection(collectionname);
24 |
25 | // Get and then check to ensure the correct index is present
26 | collection.indexInformation(function(err, indexitems) {
27 | if (err) callback(err);
28 |
29 | var index_field_required = ['loc', '2d'];
30 | var values = us.values(indexitems);
31 | var flattened = us.flatten(values);
32 | var cleaned = us.without(flattened, "_id", 1);
33 | var valid_index = us.intersection(cleaned, index_field_required);
34 |
35 | if (valid_index.length == index_field_required.length) {
36 |
37 | var location_of_interest = [ -122.21, 37.78];
38 | collection.find({'loc': {$near : location_of_interest } }).limit(3).toArray(function(err, result) {
39 | if (err) callback(err);
40 |
41 | console.log(result);
42 | db.close(function(err, result) {
43 | if (err) callback(err);
44 | }); //db.close
45 | }); // first query with explain
46 | callback(null);
47 | }
48 | else {
49 | var error = new Error("This problem requires you to create a geospatial index on the collection " + collectionname + ".");
50 | db.close(function(err, result) {
51 | if (err) callback(err);
52 | }); //db.close
53 | callback(error);
54 | }
55 | }); // indexInformation()
56 | },
57 | ],
58 | // callback and error handling
59 | function(err, results) {
60 | if (err) console.warn(err.message);
61 | });
62 | }); // connect
63 |
--------------------------------------------------------------------------------
/problems/hello_world/problem.txt:
--------------------------------------------------------------------------------
1 | Write a program that connects to a locally running MongoDB MongoD server
2 | and prints the phrase "HELLO WORLD - WE ARE CONNECTED" to the console
3 | (stdout).
4 |
5 | ----------------------------------------------------------------------
6 | {yellow}{bold}HINTS:{/bold}{/yellow}
7 |
8 | To write a Node.js program, make a new file with a `.js` extension and
9 | start writing JavaScript! Execute your program by running it with the
10 | `node` command. e.g.:
11 |
12 | {blue}{bold}$ node myprogram.js{/bold}{/blue}
13 |
14 | You can write to the console in the same way as in the browser:
15 |
16 | {green}{bold}console.log("text"){/bold}{/green}
17 |
18 | When you are done, you must run:
19 |
20 | {blue}{bold}$ {appname} verify myprogram.js{/bold}{/blue}
21 |
22 | to proceed. Your program will be tested, a report will be generated,
23 | and the lesson will be marked 'completed' if you are successful.
24 |
25 | ----------------------------------------------------------------------
26 | {yellow}{bold}NODE.JS MONGODB DRIVER APPROACHES{/bold}{/yellow}
27 |
28 | A recommend approach is to use a client variable and use this to manage your
29 | connection:
30 |
31 | {green}{bold}var MongoClient = require('mongodb').MongoClient
32 | , format = require('util').format;{/bold}{/green}
33 |
34 | A typical approach to connecting to the data with node.js involves a little
35 | bit of additional error handling and is shown below:
36 |
37 | {bold}{green}MongoClient.connect('mongodb://127.0.0.1:27017/learnmymongodb', function(err, db) {
38 | if(err) throw err;
39 |
40 | // Find / Insert / Create / Delete functions on database
41 |
42 | db.close();
43 | });{/bold}{/green}
44 |
--------------------------------------------------------------------------------
/problems/hello_world/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | return { args: [], stdin: null }
3 | }
--------------------------------------------------------------------------------
/problems/hello_world/solution.js:
--------------------------------------------------------------------------------
1 | var MongoClient = require('mongodb').MongoClient
2 | , format = require('util').format;
3 |
4 | MongoClient.connect('mongodb://127.0.0.1:27017/learnmymongodb', function(err, db) {
5 | if(err) {
6 | console.warn(err.message);
7 | return;
8 | }
9 |
10 | console.log("HELLO WORLD - WE ARE CONNECTED");
11 |
12 | db.close();
13 | });
--------------------------------------------------------------------------------
/problems/my_first_insert/problem.txt:
--------------------------------------------------------------------------------
1 | Write a program that opens a MongoDB database '{bold}learnmymongodb{/bold}',
2 | create a new collection '{bold}test2{/bold}', insert a document into
3 | the collection just created, '{bold}test2{/bold}' and return this document
4 | as part of a query excluding the '{bold}_id{/bold}' (ObjectID) of the
5 | document.
6 |
7 | The document should be written as:
8 |
9 | {blue}{bold}{
10 | "Learning" : "MongoDB"
11 | }{/blue}{/bold}
12 |
13 | Your solution will be verified by the output to the console from your query.
14 |
15 | This exercise assumes a running MongoDB on your local machine. This means
16 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/learnmymongodb'{/yellow}{/bold}.
17 |
18 | ----------------------------------------------------------------------
19 | HINTS:
20 |
21 | {grey}{italic}// Create a collection, test2{/grey}{/italic}
22 | {blue}{bold}db.createCollection('test2', function(err, collection) {
23 | if (err) console.warn(err.message);
24 | }){/blue}{/bold}
25 |
26 | {grey}{italic}// Perform a simple insert into a collection, test2{/grey}{/italic}
27 | {blue}{bold}var collection = db.collection("test2");{/blue}{/bold}
28 |
29 | {grey}{italic}// Insert a simple doc into the collection{/grey}{/italic}
30 | {blue}{bold}{
31 | collection.insert({"Learning" : "MongoDB"}, {w:1}, function(err, result) {
32 | assert.equal(null, err);
33 | });{/blue}{/bold}
34 |
35 | {grey}{italic}// To return a document excluding or including a specific field
36 | you can use the "fields" attribute and supply it with a list of value to filter.{/grey}{/italic}
37 | {blue}{bold}{
38 | collection.find({"Learning":"MongoDB"}, {"fields": {_id:0}});
39 | });{/blue}{/bold}
40 |
41 | There are a variety of ways to use the insert functionality and a good
42 | reference can be found at:
43 | {yellow}http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html{/yellow}
--------------------------------------------------------------------------------
/problems/my_first_insert/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var server = 'mongodb://127.0.0.1:27017/learnmymongodb';
3 |
4 | var MongoClient = require('mongodb').MongoClient
5 | , format = require('util').format;
6 |
7 | MongoClient.connect(server, function(err, db) {
8 | if (err) {
9 | console.warn(err.message);
10 | return;
11 | }
12 |
13 | db.collection('test2', function(err, collection) {
14 | var stream = collection.find({"Learning":"MongoDB"}, {"fields": {_id:0}}).stream();
15 | stream.on("data", function(item) {
16 | console.dir(item);
17 | });
18 |
19 | stream.on("end", function() {
20 | db.close(function(err, result) {
21 | if (err) console.warn(err.message);
22 | });
23 | });
24 |
25 | });
26 | });
27 | return {
28 | args : []
29 | , stdin : null
30 | , long : true
31 | }
32 | }
--------------------------------------------------------------------------------
/problems/my_first_insert/solution.js:
--------------------------------------------------------------------------------
1 | var MongoClient = require('mongodb').MongoClient
2 | , format = require('util').format;
3 |
4 | MongoClient.connect('mongodb://127.0.0.1:27017/learnmymongodb', function(err, db) {
5 | if(err) {
6 | console.warn(err.message);
7 | return;
8 | }
9 |
10 | var doc = {"Learning" : "MongoDB"};
11 |
12 | db.createCollection('test2', function(err, collection) {
13 | if (err) console.warn(err.message);
14 | })
15 |
16 | var collection = db
17 | .collection('test2')
18 | .insert(doc, {safe: true}, function(err, object) {
19 | if (err) console.warn(err.message);
20 | });
21 |
22 | db.collection('test2')
23 | .find(doc, {fields: {_id:0}})
24 | .toArray(function(err, object) {
25 | if (err) console.warn(err.message);
26 | console.dir(object);
27 | db.close(function(err, result) {
28 | if (err) console.warn(err.message);
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/problems/my_first_query/problem.txt:
--------------------------------------------------------------------------------
1 | Write a program that opens a MongoDB database '{bold}learnmymongodb{/bold}'
2 | and queries the collection '{bold}test{/bold}'.
3 |
4 | The collection will contain up to 5 documents with the form:
5 |
6 | {blue}{bold}{
7 | "_id" : ObjectId("XXXX"),
8 | "value" : Y
9 | }{/blue}{/bold}
10 |
11 | '{italic}value{/italic}' : '{bold}Y{/bold}'
12 | Where Y is an integer between 50 and 150.
13 |
14 | You need to find these documents and print them to the console, ordered by
15 | '{italic}value{/italic}', ascending. You should print them using the following
16 | format assuming '{italic}docs{/italic}' is the variable holding an Array of
17 | documents:
18 |
19 | {blue}{bold}console.dir(docs);{/blue}{/bold}
20 |
21 | The full path to the database is the same as previous and assumes a running
22 | MongoDB on your local machine. This means the connection string will again be
23 | {yellow}{bold}'mongodb://127.0.0.1:27017/learnmymongodb'{/yellow}{/bold}.
24 |
25 | As an aside, the ObjectId is automatically generated by MongoDB and used to
26 | uniquely identify a document. It {italic}XXXX{/italic} is a unique 12 byte object consisting of the timestamp when created, a unique machine ID, the process ID of the process which generated the document and the final value is made up of a counter which increments to ensure uniqueness within a second in a single process.
27 |
28 |
29 | ----------------------------------------------------------------------
30 | HINTS:
31 |
32 | This is similar to the first exercise and you should explore the find and sort
33 | operations as well as toArray to return the documents.
34 |
35 | There are a variety of ways to use the sort functionality and a good reference
36 | can be found at:
37 | {yellow}https://github.com/mongodb/node-mongodb-native{/yellow}
--------------------------------------------------------------------------------
/problems/my_first_query/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var server = 'mongodb://127.0.0.1:27017/learnmymongodb';
3 | var ops = []
4 | , i = 5
5 | , k;
6 |
7 | while (i-- > 0) {
8 | k = Math.floor(Math.random() * (i == 1 ? 50 : 150));
9 | ops.push( { value: k} );
10 | }
11 |
12 | var MongoClient = require('mongodb').MongoClient
13 | , format = require('util').format;
14 |
15 | MongoClient.connect(server, function(err, db) {
16 | if (err) throw err;
17 |
18 | db.createCollection('test', function(err, collection) {
19 | if (err) throw err;
20 | })
21 |
22 | db.collection('test').remove( function(err) {
23 | if (err) throw err;
24 | })
25 |
26 | db.collection('test').insert(ops, {w:1, fsync:true}, function(err, result) {
27 | if (err) console.warn(err.message);
28 | if (err && err.message.indexOf('E11000 ') !== -1) {
29 | // this _id was already inserted into the database
30 | }
31 | })
32 | }
33 | )
34 |
35 | return {
36 | args : []
37 | , stdin : null
38 | , long : true
39 | }
40 | }
--------------------------------------------------------------------------------
/problems/my_first_query/solution.js:
--------------------------------------------------------------------------------
1 | var MongoClient = require('mongodb').MongoClient
2 | , format = require('util').format;
3 |
4 | MongoClient.connect('mongodb://127.0.0.1:27017/learnmymongodb', function(err, db) {
5 | if(err) {
6 | console.warn(err.message);
7 | return;
8 | }
9 | var collection = db
10 | .collection('test')
11 | .find({})
12 | .sort({'value': '1'})
13 | .toArray(function(err, object) {
14 | if (err) console.warn(err.message);
15 | console.dir(object);
16 | db.close(function(err, result) {
17 | if (err) console.warn(err.message);
18 | });
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/problems/retrieving_and_querying_HN_stories/problem.txt:
--------------------------------------------------------------------------------
1 | In this exercise, you will USE the database '{bold}mydatabase{/bold}' running on your localhost (127.0.0.1) in port 27017 and you will CREATE the collection '{bold}hackernews{/bold}'.
2 |
3 | You will need to install an additional Node module for this exercise, 'request'. This can be installed using the {yellow}npm install request{yellow} command at your terminal / command line prompt.
4 |
5 | You will use this module to collect and save the front page news from the popular news site, Hacker News.
6 |
7 | You will create special kind of MongoDB index for this data, a text index. In order to create this type of index, you will need to enable text search in MongoDB (see {yellow}http://docs.mongodb.org/manual/tutorial/enable-text-search/{/yellow} for more details).
8 |
9 | The format of the page result you will receive as a JSON object contains the following:
10 | {blue}{bold}nextId:{/bold} ID for next page of links
11 | {bold}items:{/bold} array of links, which each link contain the following fields: commentCount, id, points, postedAgo, postedBy, title, url
12 | {bold}cachedOnUTC:{/bold} UTC date and time when request was cached{/blue}
13 |
14 | Stage 1 - Download and install the NodeJS module, 'request'. This can be done using NPM (npm install request) or visit the project webpage for more details (https://github.com/mikeal/request).
15 |
16 | Stage 2 - Connect to the Hacker News API and download the current news from its front page using this URL, {yellow}http://api.ihackernews.com/page{/yellow}.
17 |
18 | Stage 3 - Connect to the database, {bold}'mydatabase'{/bold} and import the current front page news of 'hacker news' into a new collection, {bold}'hackernews'{/bold}.
19 |
20 | Stage 4 - Enable the text search capability in MongoBD, this will require you running a command against the {bold}Admin{/bold} database or setting the parameter for your MongoDB when you start it. You must then create a text index on {bold}"title"{/bold} field.
21 |
22 | Stage 5 - Use MongoDB's text command to search the collection for the phrase {bold}"show hn"{bold} and print the results field to the console. You will need to use a different form of query for this with a format of {bold}'db.command({"text": collectionname, "search": searchstring})'{bold} as text search (in 2.4) does not support the 'find' method as it is still experimental.
23 |
24 | Your answer to the exercise will be run against the official solution to ensure
25 | that your query returns the correctly documents.
26 |
27 | This exercise assumes a running MongoDB on your local machine. This means
28 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/'{/yellow}{/bold}.
29 |
30 | ----------------------------------------------------------------------
31 | HINTS
32 |
33 | In this exercise, you will need to use install the 'request' module and the specific page you should gather the data from is 'http://api.ihackernews.com/page'.
34 |
35 | You MUST also enable {bold}text search{/bold} in your MongoDB as this is not enabled by default (see {yellow}http://docs.mongodb.org/manual/tutorial/enable-text-search/{/yellow} for more details).
36 |
37 | The MongoDB text index tutorial can be found at:
38 | {yellow}http://docs.mongodb.org/manual/tutorial/create-text-index-on-multiple-fields/{/yellow}
39 |
40 | The MongoDB Node Driver manual on the Admin database can be found at:
41 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/admin.html{/yellow}
--------------------------------------------------------------------------------
/problems/retrieving_and_querying_HN_stories/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var async = require('async');
3 |
4 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
5 | var collectionname = 'hackernews';
6 | var MongoClient = require('mongodb').MongoClient
7 | , format = require('util').format;
8 |
9 | async.series([
10 | // Setup for the exercise by ensuring there is no existing data
11 | function(callback) {
12 | MongoClient.connect(server, function(err, db) {
13 | if (err) return callback(err);
14 |
15 | db.dropCollection(collectionname, function(err, result) {
16 | if (err) return callback(err);
17 | db.close(function(err, result) {
18 | if (err) return callback(err);
19 | }); //db.close
20 | }); //db.dropCollection
21 | }); // MongoClient.connect
22 | callback(null);
23 | } // callback
24 | ],
25 | // callback and error handling
26 | function(err, results) {
27 | if (err) console.warn(err.message);
28 | });
29 |
30 | return { args: [], stdin: null }
31 | }
32 |
--------------------------------------------------------------------------------
/problems/retrieving_and_querying_HN_stories/solution.js:
--------------------------------------------------------------------------------
1 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
2 | var databasename = 'mydatabase';
3 | var collectionname = 'hackernews';
4 | var MongoClient = require('mongodb').MongoClient
5 | , format = require('util').format;
6 | var async = require('async');
7 | var us = require('underscore');
8 |
9 | // The sleep module and call are used to delay the execution of the solution script to ensure
10 | // it does not check for the existing of the DB created by your program before it has a chance
11 | // to create the database. A lock file or other approach will be used in future.
12 | var sleep = require('sleep');
13 | sleep.sleep(1);
14 |
15 | MongoClient.connect(server, function(err, db) {
16 | if (err) {
17 | console.warn(err.message);
18 | return;
19 | }
20 | async.series([
21 | // Deterime if the specified database exits
22 | function(callback) {
23 | var collection = db.collection(collectionname);
24 |
25 | collection.indexInformation(function(err, indexitems) {
26 | if (err) callback(err);
27 |
28 | var index_key_items = ['text'];
29 | var values = us.values(indexitems);
30 | var flattened = us.flatten(values);
31 | var cleaned = us.without(flattened, "_id", 1);
32 | var valid_index = us.intersection(cleaned, index_key_items);
33 |
34 | if (valid_index.length == index_key_items.length) {
35 | var searchstring = "ask hn";
36 | db.command({"text": collectionname, "search": searchstring}, function(err, searchresult) {
37 | if (err) callback(err);
38 |
39 | console.log(searchresult.results);
40 | db.close(function(err, result) {
41 | if (err) callback(err);
42 | }); //db.close
43 | }); //db.command
44 |
45 | callback(null);
46 | }
47 | else {
48 | console.log("This problem requires you to create an index on the collection " + collectionname + " for the field " + index_key_items.toString() + ".");
49 | db.close(function(err, result) {
50 | if (err) callback(err);
51 | }); //db.close
52 | callback(null);
53 | }
54 | }); // indexInformation()
55 | },
56 | ],
57 | // callback and error handling
58 | function(err, results) {
59 | if (err) console.warn(err.message);
60 | });
61 | }); // connect
62 |
--------------------------------------------------------------------------------
/problems/storing_an_image_with_gridfs/problem.txt:
--------------------------------------------------------------------------------
1 | In this exercise, you will USE the database '{bold}mydatabase{/bold}' running on your localhost (127.0.0.1) in port 27017 and you will CREATE the collection '{bold}imagecollection{/bold}'.
2 |
3 | You will need to install an additional Node module for this exercise, 'request'. This can be installed using the {yellow}npm install request{yellow} command at your terminal / command line prompt.
4 |
5 | You will use this module to retrieve the MongoDB logo from the MongoDB site and save this image file into your database using gridFS. This approach allows you to store files larger than the document limit of 16MB in MongoDB. In this case, MongoDB acts as a file storage system though the use of a files collection (fs.files) and a chunks collection (fs.chunks) where the file is stored by being split into chunks and referenced from the record of the file in the files collection (see {yellow}http://docs.mongodb.org/manual/core/gridfs/{/yellow} for more details).
6 |
7 | Stage 1 - Download and install the NodeJS module, 'request'. This can be done using NPM (npm install request) or visit the project webpage for more details (https://github.com/mikeal/request).
8 |
9 | Stage 2 - Retrieve the file 'logo-mongodb.png' from the server 'http://media.mongodb.org/' (full url: http://media.mongodb.org/logo-mongodb.png) and store this in your local directory for use as the file that will be put into the database.
10 |
11 | Stage 3 - Connect to the database, {bold}'mydatabase'{/bold} and determine necessary information about the file 'logo-mongodb.png' prior to storing in GridFS. You will need to use the 'fs' module to open the file and gather the 'stat' information from the file to determine it's size prior to storing it in the database.
12 |
13 | Stage 4 - Store the file 'logo-mongodb.png' in the database, {bold}'mydatabase'{/bold} using GridFS, this can be done in a number of ways (e.g. using Grid or GridStore for details see {yellow}http://mongodb.github.io/node-mongodb-native/api-articles/nodekoarticle2.html{/yellow}).
14 |
15 | Stage 5 - Update the metadata associated with the file in the 'fs.files' collection and set the metadata using an update operation where the ObjectID obtained in Stage 4 to insert the file is used as part of your query. The format of the metadata is given below and the '$set' operator should be used to modify as well as creating any fields in the document rather than simply replacing the existing document.
16 |
17 | Stage 6 - Query the 'fs.files' collection for the ObjectID obtained in Stage 4 using the 'findOne' method and print the results of this method to the console.
18 |
19 | {blue}{"filename": "logo-mongodb.png", "contentType": "image/png","metadata":{"author": "MongoDB Inc."}}{/blue}
20 |
21 | Your answer to the exercise will be run against the official solution to ensure
22 | that your query returns the correctly documents.
23 |
24 | This exercise assumes a running MongoDB on your local machine. This means
25 | the connection string will again be {yellow}{bold}'mongodb://127.0.0.1:27017/'{/yellow}{/bold}.
26 |
27 | ----------------------------------------------------------------------
28 | HINTS
29 |
30 | In this exercise, you will need to use install the 'request' module and the specific image you should download and save to the database is found at {yellow}http://media.mongodb.org/logo-mongodb.png{/yellow}.
31 |
32 | The MongoDB GridStore reference can be found at:
33 | {yellow}http://docs.mongodb.org/manual/core/gridfs/{/yellow}
34 |
35 | The MongoDB Node Driver manual on the GridStore can be found at:
36 | {yellow}http://mongodb.github.io/node-mongodb-native/api-generated/gridstore.html{/yellow}
--------------------------------------------------------------------------------
/problems/storing_an_image_with_gridfs/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | var async = require('async');
3 |
4 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
5 | var filescollectionname = 'fs.files';
6 | var chunkscollectionname = 'fs.chunks';
7 | var MongoClient = require('mongodb').MongoClient
8 | , format = require('util').format;
9 |
10 | async.series([
11 | // Setup for the exercise by ensuring there is no existing data
12 | function(callback) {
13 | MongoClient.connect(server, function(err, db) {
14 | if (err) return callback(err);
15 |
16 | db.dropCollection(filescollectionname, function(err, result) {
17 | if (err) return callback(err);
18 |
19 | db.dropCollection(chunkscollectionname, function(err, result) {
20 | if (err) return callback(err);
21 |
22 | db.close(function(err, result) {
23 | if (err) return callback(err);
24 | }); //db.close
25 | }); // db.dropCollection - chunks
26 | }); //db.dropCollection - files
27 | }); // MongoClient.connect
28 | callback(null);
29 | } // callback
30 | ],
31 | // callback and error handling
32 | function(err, results) {
33 | if (err && err.message != "ns not found") console.warn(err.message);
34 | });
35 |
36 | return { args: [], stdin: null }
37 | }
38 |
--------------------------------------------------------------------------------
/problems/storing_an_image_with_gridfs/solution.js:
--------------------------------------------------------------------------------
1 | var server = 'mongodb://127.0.0.1:27017/mydatabase';
2 | var MongoClient = require('mongodb').MongoClient
3 | , format = require('util').format;
4 | var filesCollection = 'fs.files';
5 | var databasename = 'mydatabase';
6 | var async = require('async');
7 | var fs = require('fs');
8 | var path = require('path');
9 | var request = require('request');
10 | var mongodb_media_url = 'http://media.mongodb.org/';
11 | var mongodb_logo_filename = 'logo-mongodb.png';
12 | var ObjectID = require('mongodb').ObjectID;
13 | var GridStore = require('mongodb').GridStore;
14 |
15 | // Part of checking that it is indeed same file is to download separately and md5 hash it then check against stored hash in DB
16 | var crypto = require('crypto');
17 | var algo = 'md5';
18 | var shasum = crypto.createHash(algo);
19 | var filemd5;
20 |
21 | var us = require('underscore');
22 |
23 | // The sleep module and call are used to delay the execution of the solution script to ensure
24 | // it does not check for the existing of the DB created by your program before it has a chance
25 | // to create the database. A lock file or other approach will be used in future.
26 | var sleep = require('sleep');
27 | sleep.sleep(1);
28 |
29 | MongoClient.connect(server, function(err, db) {
30 | if (err) {
31 | console.warn(err.message);
32 | return;
33 | }
34 | async.series([
35 | // Deterime if the specified database exits
36 | function(callback) {
37 | db.collectionNames(function(err, collectionslistfordb) {
38 | if (err) callback(err);
39 |
40 | var collectionnames_to_find = ['fs.files','fs.chunks'];
41 | var valid_gridfs_on_db = us.intersection(collectionslistfordb, collectionnames_to_find);
42 |
43 | if (us.difference(valid_gridfs_on_db, collectionnames_to_find).length == 0) {
44 |
45 | var authormetadata = {"metadata":{"author": "MongoDB Inc."}};
46 | var collection = db.collection(filesCollection);
47 |
48 | try {
49 | var fd = fs.openSync(path.join(__dirname, mongodb_logo_filename),'r+');
50 | var filecontents = fs.readFileSync(path.join(__dirname, mongodb_logo_filename));
51 | shasum.update(filecontents);
52 | filemd5 = shasum.digest('hex');
53 | fs.closeSync(fd);
54 | }
55 | catch (error) {
56 | callback(error);
57 | }
58 |
59 |
60 | collection.findOne(authormetadata, function(err, result) {
61 | if (err) callback(err);
62 |
63 | if ( result.md5 != filemd5 ) {
64 | var error = new Error ("Different MD5 hashes between file on disk and record in GridFS DB.")
65 | callback(error);
66 | }
67 |
68 | console.log(result);
69 |
70 | db.close(function(err, result) {
71 | if (err) callback(err.message);
72 | }); //db.close
73 | callback(null);
74 | }); // update
75 |
76 | }
77 | else {
78 | var error = new Error("This problem requires you to have stored a file in GridFS using the collections " + collectionnames_to_find + ".");
79 | db.close();
80 | callback(error);
81 | }
82 | callback(null);
83 | }); // db.collectionNames
84 | },
85 | ],
86 | // callback and error handling
87 | function(err, results) {
88 | if (err) console.warn(err.message);
89 | });
90 | }); // connect
91 |
--------------------------------------------------------------------------------