├── .gitignore ├── README.md ├── module1_intro_doc_dbs ├── .DS_Store └── README.md ├── module2_getting_started ├── .DS_Store ├── README.md ├── ScreenShots │ ├── .DS_Store │ ├── mongodbss1.png │ └── mongodbss2.png └── bank_data.json.zip ├── module3_language_drivers ├── CSharpEnd │ ├── App.config │ ├── MongoSample.csproj │ ├── MongoSample.sln │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── packages.config ├── CSharpStart │ ├── App.config │ ├── MongoSample.csproj │ ├── MongoSample.sln │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── packages.config ├── End │ ├── app.js │ └── package.json ├── README.md ├── ScreenShots │ ├── mongo-csharp1.png │ ├── mongo-csharp2.png │ ├── mongo-csharp3.png │ ├── mongo-csharp4.png │ ├── mongo-csharp5.png │ └── mongo-csharp6.png └── Start │ ├── app.js │ └── package.json ├── module4_advanced_data_ops ├── End │ ├── app.js │ └── package.json ├── README.md ├── ScreenShots │ ├── mongodbss1.png │ ├── mongodbss2.png │ └── mongodbss3.png └── Start │ ├── app.js │ └── package.json └── module5_running_in_cloud ├── .DS_Store ├── README.md └── ScreenShots ├── ss1.png ├── ss2.png ├── ss3.png ├── ss4.png ├── ss5.png ├── ss6.png ├── ss7.png └── ss8.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | You've Got Documents! A MongoDB Jump Start 2 | =========== 3 | 4 | This is a [Microsoft Virtual Academy](http://www.microsoftvirtualacademy.com/liveevents/you-ve-got-documents-a-mongodb-jump-start) course on getting started with MongoDB. 5 | 6 | ## [Module 1: Introduction to Document Oriented Databases](https://github.com/sedouard/mongodb-mva/tree/master/module1_intro_doc_dbs) 7 | 8 | Introductory module covering the basics of document oriented databases vs tabular databases. In this module you'll understand the fundamental organization of document databases. 9 | 10 | ## [Module 2: Getting Started with MongoDB Queries](https://github.com/sedouard/mongodb-mva/tree/master/module2_getting_started) 11 | 12 | This section covers installing and loading up bulk data into MongoDB. Querying is covered via the MongoDB Interactive Shell covering operators such as $or and $elemMatch. 13 | 14 | ## [Module 3: Language Drivers](https://github.com/sedouard/mongodb-mva/tree/master/module3_language_drivers) 15 | 16 | The Language Drivers section covers how you can use MongoDB right from your application. Create, Remove, Update, and Delete operations are covered in Node.js and in C#. 17 | 18 | ## [Module 4: Advanced Data Processing](https://github.com/sedouard/mongodb-mva/tree/master/module4_advanced_data_ops) 19 | 20 | In Advanced Data Processing, Map Reduce and Aggregations are covered by answering some interesting questions about the Chicago Crimes Database. This Crimes database contains over 5 million police reports filed in Chicago between 2001 and November 2014. 21 | 22 | ## [Module 5: Running MongoDB In the Cloud](https://github.com/sedouard/mongodb-mva/tree/master/module5_running_in_cloud) 23 | 24 | In this section, we'll go over how you can run MongoDB in an Ubuntu Virtual Machine. The module covers opening the MongoDB endpoint on the server as well as configuring MongoDB to be accessible from your client application. 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /module1_intro_doc_dbs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module1_intro_doc_dbs/.DS_Store -------------------------------------------------------------------------------- /module1_intro_doc_dbs/README.md: -------------------------------------------------------------------------------- 1 | # Module 1: Introduction to NoSQL Document Oriented Databases 2 | 3 | -------- 4 | ## Objectives 5 | 6 | By the end of this module you will be able to: 7 | 8 | - Understand the difference between Documented Oriented Databases, Structured Databases and SQL Databases 9 | - How a Document Oriented Database is laid out 10 | 11 | ## Introduction 12 | 13 | [Document Oriented Databases](http://en.wikipedia.org/wiki/Document-oriented_database) are a relatively new type of data store which organizes data radically different than your traditional SQL store. Rather than storing items in a variety of tables, document databases like [MongoDB](http://mongodb.org) store data in 'documents' which wholly describe an entire entity in your application. 14 | 15 | This data organization scheme eliminates the need for most [joins](http://en.wikipedia.org/wiki/Join_(SQL)) between tables to collect information associated with an entity. In general, document oriented databases are best suited for data need which involve a large amount of one:one and one:many relationships. 16 | 17 | Further, storage databases like MongoDB don't have strict entity relationship structures like SQL introduces. Most notably, there is no such thing as [foriegn keys](http://en.wikipedia.org/wiki/Foreign_key) or build-in columns which are used to identify keys in other tables. Traditionally this is a pain point when trying to make any large data organization changes to a SQL database. 18 | 19 | ## Tabluar Structured Data vs Document Structure 20 | 21 | 22 | Lets look at an example of a bank, which keeps track of the following entities: 23 | 24 | - **Person** 25 | - **Account** 26 | 27 | The basic relation here is that a **Person** can have many **Accounts** and therefore an **Account** has only one **Person**. 28 | 29 | ### Tabular Structure 30 | 31 | Here's what this data may look like in a SQL database 32 | 33 | **Persons:** 34 | 35 | 36 | ID | FIRST_NAME | LAST_NAME 37 | ------------- | ------------- | ------------- 38 | 0 | Steven | Edouard 39 | 1 | Sam | Brightwood 40 | 41 | 42 | **Accounts** 43 | 44 | ID | ACCOUNT_TYPE | ACCOUNT_BALANCE | CURRENCY | HOLDER (FK: Persons) 45 | ------------- | ------------- | ------------- | ------------- | ------------- 46 | 0 | Investment | 80000.00 | USD | 0 47 | 1 | Savings | 70400.00 | USD | 0 48 | 2 | Checking | 4500.00 | USD | 0 49 | 3 | Checking | 4500.00 | YEN | 1 50 | 4 | Investment | 4500.00 | YEN | 1 51 | 5 | Savings | 4500.00 | YEN | 1 52 | 53 | In the above data schema, the **HOLDER** field in the **Accounts** table is a **Foriegn Key** into the **Accounts** table. This is what creates the association between the two data entities. SQL actually requires that in order to create an Account, you must have a valid Foreign key that points to an existing person, which can cause some loss in flexibility. 54 | 55 | With the schema above its easy to answer the question: 56 | 57 | *Who is the account holder for account with ID = 3?* 58 | 59 | Because we have a foreign key HOLDER for the account we can quickly and easily look up that the account holder is **Sam Brightwood**. This is because there is a **many:one** relation ships from Account entities and Person entities. 60 | 61 | Now, how about the question: 62 | 63 | *Which accounts does person Steven Edouard hold?* 64 | 65 | To answer this question, it requires us to do a **join** which essentially is a set operation to find all of the rows in the **Accounts** table which match the Person ID = 0. This can become an expensive operation as the data in the tables grow toward larger and larger numbers. 66 | 67 | ### Document Oriented Structure 68 | 69 | The same data above can be described in a document oriented database with a JSON-like syntax: 70 | 71 | ```json 72 | # Person Collection (Person is the root entity) 73 | [ 74 | { 75 | "ID": 0, 76 | "first_name": "Steven", 77 | "last_name": "Edouard", 78 | "accounts": [ 79 | { 80 | "id": 0, 81 | "account_type": "Investment", 82 | "account_balance": "80000.00", 83 | "currency": "USD" 84 | }, 85 | { 86 | "id": 1, 87 | "account_type": "Savings", 88 | "account_balance": "70400.00", 89 | "currency": "USD" 90 | }, 91 | { 92 | "id": 2, 93 | "account_type": "Checking", 94 | "account_balance": "80000.00", 95 | "currency": "USD" 96 | } 97 | ] 98 | } 99 | { 100 | "ID": 1, 101 | "first_name": "Sam", 102 | "last_name": "Brightwood", 103 | "accounts":[ 104 | 105 | { 106 | "id": 3, 107 | "account_type": "Checking", 108 | "account_balance": "4500.00", 109 | "currency": "YEN" 110 | } 111 | { 112 | "id": 4, 113 | "account_type": "Investment", 114 | "account_balance": "4500.00", 115 | "currency": "YEN" 116 | }, 117 | { 118 | 119 | "id": 5, 120 | "account_type": "Savings", 121 | "account_balance": "4500.00", 122 | "currency": "YEN" 123 | } 124 | ] 125 | } 126 | 127 | ] 128 | 129 | ``` 130 | Now, let's answer the original two questions again: 131 | 132 | *Who is the account holder for account with ID = 3?* 133 | 134 | To answer this question we can just look up the account with the unique ID 3, and by finding that account, we automatically pull the associated user. This is just as fast as the tabular organization. 135 | 136 | *Which accounts does person Steven Edouard hold?* 137 | 138 | This question can be answered by looking for the person with ```first_name="Steven"``` and ```last_name="Edouard"``. Once we locate that person, the associated accounts are automatically found since they are associated in the database organization. This type of query proves to be much faster than the tabular approach. 139 | 140 | Notice how this looks *very* different than the tabular representation. This is a very clever way of storing our data because it the relationship between Persons and Accounts is inherent in the structure of the data. Meaning, when we retrieve the Person, Steven Edouard, we also retrieve all of his bank accounts, eliminating the need for any expensive joins here. 141 | 142 | This is the fundamental difference between NoSQL Document stores and SQL databases. 143 | 144 | 145 | -------------------------------------------------------------------------------- /module2_getting_started/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module2_getting_started/.DS_Store -------------------------------------------------------------------------------- /module2_getting_started/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started With MongoDB Queries 2 | 3 | ## Objectives 4 | 5 | By the end of this module you will know how to: 6 | 7 | - Install, setup and run MongoDB on your local machine 8 | - Load bulk data from a text file into MongoDB using mongoimport 9 | - Use the Interactive Shell to run basic queries using [query documents](http://docs.mongodb.org/manual/tutorial/query-documents/) 10 | - Use operators such as $gt and $or for queries and [projections](http://docs.mongodb.org/manual/tutorial/query-documents/). 11 | 12 | ## Getting Started 13 | 14 | The first thing you need to do is [install mongodb](http://docs.mongodb.org/manual/installation/) for your specific system. Follow the instructions for mongodb for your operating system. 15 | 16 | You should setup mongodb such that you have it installed in an easy to access directory such as 17 | 18 | ```bash 19 | # linux/unix 20 | /mongodb 21 | # windows 22 | C:\mongodb 23 | ``` 24 | 25 | Now that you have MongoDB installed you need to create a data directory for it to store data to the disk. Execute the following commands from your **bin** folder in your mongodb installation: 26 | 27 | ```bash 28 | mkdir /data/db 29 | ``` 30 | Now that we have our data directory you can run the mongodb database process 31 | 32 | **mongod**: 33 | 34 | ```bash 35 | mongod 36 | ``` 37 | 38 | This starts up the MongoDB server and indicates we can start inserting data. 39 | 40 | ## MongoDB Database Organization 41 | 42 | Similar to other database systems, Mongodb data organization starts with the database server (the **mongod** process). Each server may have N number of databases and within each database there are N number of [collections](http://docs.mongodb.org/manual/reference/glossary/#term-collection). 43 | 44 | ![](ScreenShots/mongodbss2.png) 45 | 46 | This structure allows for more advance scaling such as [sharding](http://docs.mongodb.org/manual/sharding/) to provide more throughput and [replicase sets](http://docs.mongodb.org/manual/core/replication/) for better redundancy. 47 | 48 | ## Loading up test data into mongodb 49 | 50 | Within the data directory of this repository there is a **bank_data.json.zip** file; you should decompress it. We will use this file to load up the bank data collection into mongodb. From the mongodb installation **bin** in a new console window, execute the command: 51 | 52 | ```bash 53 | mongoimport --jsonArray --collection bank_data 54 | ``` 55 | The command will actually load up the json data in the file up into a collection called 'bank_data' in your default MongoDB database on your mongodb server. This may take a while however you'll be able to keep track of the percentage: 56 | 57 | ```bash 58 | Users-Computer-4:bin user$ ./mongoimport /Users/user/Documents/crimeDataConvert/data/bank_data.json --jsonArray --collection bank_data 59 | connected to: 127.0.0.1 60 | 2014-11-16T02:11:10.797-0800 Progress: 192824/22758676 0% 61 | 2014-11-16T02:11:10.797-0800 400 133/second 62 | 2014-11-16T02:11:13.316-0800 Progress: 340537/22758676 1% 63 | 2014-11-16T02:11:13.316-0800 700 116/second 64 | 2014-11-16T02:11:16.648-0800 Progress: 533438/22758676 2% 65 | 2014-11-16T02:11:16.648-0800 1100 122/second 66 | ``` 67 | 68 | After all of this 50,000 documents will be uploaded into your local MongoDB server. Although that may sound like a lot, its likely a manageable size to work with on your computer. 69 | 70 | Now that all your bank accounts data has been loaded up into MongoDB we are ready to start exploring! 71 | 72 | ## The MongoDB Interactive Shell 73 | 74 | MongoDB has an interactive shell which is very similar to the javascript interactive shell except it includes a mongodb api. Most commands are actually javascript however are slightly different than the Node.js javascript version we will work with in [module 3](../module3_language_drivers/README.md). To run the shell execute the following command from your mongodb installation **bin** folder: 75 | 76 | ```bash 77 | mongo 78 | ``` 79 | 80 | This will automatically connect you to your local mongodb server running in your other console window. 81 | 82 | If you ever want to explore anything outside of this guide in the interactive shell, you can get more info by doing: 83 | 84 | ```bash 85 | help 86 | ``` 87 | 88 | The remainder of this module will use the MongoDB Interactive Shell to explore MongoDB capabilities. [Module 3](../module3_language_drivers/README.md) will focus on the [C#] (http://docs.mongodb.org/ecosystem/drivers/csharp/)and [Node.js](http://docs.mongodb.org/ecosystem/drivers/node-js/) language drivers. 89 | 90 | ### Collections 91 | 92 | Collections in in MongoDB are containers for a group of similar entities. In our example from module1 the **Person** entity was the root entity. A single database can have many collections. To display the collections in your database execute: 93 | 94 | ``` 95 | # shows collections in database 96 | show collections 97 | ``` 98 | 99 | The output of your command will look similar to: 100 | 101 | ```bash 102 | > show collections 103 | bank_data 104 | system.indexes 105 | 106 | ``` 107 | 108 | To get the collection object, we can use the **db** reference to the current database. 109 | 110 | ```bash 111 | db.bank_data 112 | ``` 113 | To see how many documents we loaded into the mongodb collection we can use the **count()** function on the collection object: 114 | 115 | ```bash 116 | > db.bank_data.count() 117 | 50000 118 | ``` 119 | 120 | There's much more you can do with a collection. Checkout the collections help by doing: 121 | 122 | ```bash 123 | db.bank_data.help() 124 | ``` 125 | 126 | ### Queries 127 | 128 | Now that we have bulk data loaded up we can make some queries across the Person collection. All queries in MongoDB use the **find** function on the query to get specific documents from the collection. Let's try our first query with the .findOne method which finds the first document in the collection. 129 | 130 | ```js 131 | db.bank_data.findOne() 132 | ``` 133 | 134 | This command should return something similar to: 135 | 136 | ```json 137 | { 138 | "_id" : ObjectId("5468782fca357ca95f2f4b88"), 139 | "first_name" : "JAMES", 140 | "last_name" : "SMITH", 141 | "accounts" : [ 142 | { 143 | "account_type" : "Investment", 144 | "account_balance" : 6144974.110823463, 145 | "currency" : "YEN" 146 | }, 147 | { 148 | "account_type" : "Savings", 149 | "account_balance" : 1329372.569229168, 150 | "currency" : "EURO" 151 | } 152 | ] 153 | } 154 | ``` 155 | 156 | Like our example from [module 1](../module1_intro_doc_dbs/README.md) we get a Person document with a number of Account sub documents within it. This query didn't really have anything interesting to it. We simply wanted to retrieve the first person in Person collection (that is what MongoDB interpreted when we didn't specify any parameters into the *findOne()* function). 157 | 158 | Let's see what happens when you execute: 159 | 160 | ```js 161 | db.collection.find() 162 | ``` 163 | 164 | You'll actually get a ton of text similar to: 165 | 166 | ```json 167 | 168 | { "_id" : ObjectId("5468782fca357ca95f2f4b88"), "first_name" : "JAMES", "last_name" : "SMITH", "accounts" : [ { "account_type" : "Investment", "account_balance" : 6144974.110823463, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 1329372.569229168, "currency" : "EURO" } ] } 169 | { "_id" : ObjectId("54687830ca357ca95f2f4b89"), "first_name" : "JAMES", "last_name" : "JOHNSON", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9840052.941285312, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 5588991.2251258055, "currency" : "PESO" }, { "account_type" : "Savings", "account_balance" : 4235557.4669413585, "currency" : "POUNDS STERLING" }, { "account_type" : "Savings", "account_balance" : 8799224.831341146, "currency" : "YEN" }, { "account_type" : "401K", "account_balance" : 5962745.686764822, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 9818556.57020622, "currency" : "POUNDS STERLING" }, { "account_type" : "Investment", "account_balance" : 6418584.010852241, "currency" : "EURO" } ] } 170 | { "_id" : ObjectId("54687830ca357ca95f2f4b8a"), "first_name" : "JAMES", "last_name" : "WILLIAMS", "accounts" : [ { "account_type" : "Investment", "account_balance" : 4904214.484536952, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 8618841.25467285, "currency" : "YUAN" }, { "account_type" : "Investment", "account_balance" : 913765.1830773808, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 1376331.8743719491, "currency" : "PESO" }, { "account_type" : "Investment", "account_balance" : 7871363.623830194, "currency" : "PESO" }, { "account_type" : "Checking", "account_balance" : 6203323.441020354, "currency" : "YUAN" }, { "account_type" : "Investment", "account_balance" : 917203.6349922416, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 5979093.451052592, "currency" : "PESO" } ] } 171 | { "_id" : ObjectId("54687830ca357ca95f2f4b8b"), "first_name" : "JAMES", "last_name" : "BROWN", "accounts" : [ { "account_type" : "Checking", "account_balance" : 5155.384490680648, "currency" : "EURO" } ] } 172 | { "_id" : ObjectId("54687830ca357ca95f2f4b8c"), "first_name" : "JAMES", "last_name" : "JONES", "accounts" : [ { "account_type" : "Savings", "account_balance" : 1871922.5181302335, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 2454099.221148599, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 8873605.096902523, "currency" : "PESO" }, { "account_type" : "Checking", "account_balance" : 7345421.697284348, "currency" : "POUNDS STERLING" }, { "account_type" : "Savings", "account_balance" : 6429599.448691073, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 6569446.0432147905, "currency" : "YUAN" }, { "account_type" : "401K", "account_balance" : 2952708.430080968, "currency" : "EURO" } ] } 173 | { "_id" : ObjectId("54687830ca357ca95f2f4b8d"), "first_name" : "JAMES", "last_name" : "MILLER", "accounts" : [ { "account_type" : "Checking", "account_balance" : 5000794.5164514, "currency" : "EURO" } ] } 174 | { "_id" : ObjectId("54687830ca357ca95f2f4b8e"), "first_name" : "JAMES", "last_name" : "DAVIS", "accounts" : [ { "account_type" : "401K", "account_balance" : 1634239.7192724317, "currency" : "EURO" }, { "account_type" : "Checking", "account_balance" : 5123875.592675053, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 9652688.997844521, "currency" : "PESO" }, { "account_type" : "401K", "account_balance" : 436608.31229717913, "currency" : "YUAN" } ] } 175 | { "_id" : ObjectId("54687830ca357ca95f2f4b8f"), "first_name" : "JAMES", "last_name" : "GARCIA", "accounts" : [ { "account_type" : "Investment", "account_balance" : 3928991.3192649623, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 4061586.788287755, "currency" : "YUAN" }, { "account_type" : "Investment", "account_balance" : 3907978.032141935, "currency" : "POUNDS STERLING" }, { "account_type" : "Checking", "account_balance" : 7980062.845765791, "currency" : "EURO" }, { "account_type" : "Investment", "account_balance" : 5629389.621828526, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 2822423.1437263936, "currency" : "PESO" }, { "account_type" : "401K", "account_balance" : 5603218.9455431765, "currency" : "EURO" } ] } 176 | ``` 177 | 178 | You'll see the ```Type "it" for more``` prompt because the **find()** method called without any parameters retrieves ALL documents in the collection. Since you have so many documents in the collection MongoDB will give us a [cursor](http://en.wikipedia.org/wiki/Cursor_(databases)) which will allow us to iterate through the results in a more manageable fashion. 179 | 180 | We can always do a **count()** over the results to see how many documents were retrieved as a result of the query. For example: 181 | 182 | ```js 183 | db.bank_data.find().count() 184 | ``` 185 | Will return the number of documents in the collection since *find()* has no parameters: 186 | 187 | ```json 188 | 50000 189 | ``` 190 | 191 | 192 | 193 | Let's look at some of basic queries and those with **AND**, **OR**, **Greater Than/Less Than/NotEqual**: 194 | 195 | ### Basic Queries with Filters 196 | 197 | The **find** function takes sort of an object projection to return the desired set of documents. For example, to return all Person documents with the last name = "Smith" we can do: 198 | 199 | ```js 200 | db.bank_data.find({last_name : "SMITH"}).count() 201 | ``` 202 | 203 | And we'll see how many people exist in the database with the last name, SMITH: 204 | 205 | ``` 206 | 100 207 | ``` 208 | 209 | We can pick out a record to display by selecting a number on the collection between 0 and 100 for this example: 210 | 211 | ```js 212 | db.bank_data.find({last_name : "SMITH"})[12] 213 | ``` 214 | 215 | This will return the 13th record in the result: 216 | 217 | ```json 218 | { 219 | "_id" : ObjectId("546960b6ca357ca95f301689"), 220 | "first_name" : "CHRISTOPHER", 221 | "last_name" : "SMITH", 222 | "accounts" : [ 223 | { 224 | "account_type" : "Savings", 225 | "account_balance" : 1870338.5807330757, 226 | "currency" : "POUNDS STERLING" 227 | }, 228 | { 229 | "account_type" : "Checking", 230 | "account_balance" : 5098043.412530517, 231 | "currency" : "POUNDS STERLING" 232 | }, 233 | { 234 | "account_type" : "Checking", 235 | "account_balance" : 3042158.5783834355, 236 | "currency" : "YEN" 237 | }, 238 | { 239 | "account_type" : "Investment", 240 | "account_balance" : 2721431.0181220435, 241 | "currency" : "PESO" 242 | }, 243 | { 244 | "account_type" : "Savings", 245 | "account_balance" : 2135388.570106006, 246 | "currency" : "USD" 247 | }, 248 | { 249 | "account_type" : "Savings", 250 | "account_balance" : 2416831.8654360515, 251 | "currency" : "PESO" 252 | }, 253 | { 254 | "account_type" : "Savings", 255 | "account_balance" : 405349.36727577704, 256 | "currency" : "POUNDS STERLING" 257 | }, 258 | { 259 | "account_type" : "Investment", 260 | "account_balance" : 6140519.315997784, 261 | "currency" : "YEN" 262 | } 263 | ] 264 | } 265 | 266 | ``` 267 | 268 | Notice how we retrieved all the accounts as well, even though we only specified the persons last name. This is because when we query we are querying for documents and therefore any associated information is also retrieved. 269 | 270 | It's possible to omit the associated information by specifying a second [projection](http://docs.mongodb.org/manual/reference/operator/projection/positional/) object to the *find()* function: 271 | 272 | ```js 273 | db.bank_data.find({last_name : "SMITH"}, {first_name : 1, last_name: 1})[12] 274 | ``` 275 | 276 | ```json 277 | { 278 | "_id" : ObjectId("546960b6ca357ca95f301689"), 279 | "first_name" : "CHRISTOPHER", 280 | "last_name" : "SMITH" 281 | } 282 | ``` 283 | 284 | Notice how the output above omits all the accounts for CHRISTOPHER SMITH. 285 | 286 | We can also output the names of each person who came in the result set pretty easily by iterating through the result collection by saving it to a variable 287 | 288 | ```js 289 | var smithPersons = db.bank_data.find({last_name : "SMITH"}, {first_name : 1, last_name: 1}); 290 | for(var i = 0; i < smithPersons.count(); i++){ 291 | print(smithPersons[i].first_name + ' ' + smithPersons[i].last_name ); 292 | } 293 | ``` 294 | You'll see a long list of output similar to the following: 295 | 296 | ``` 297 | JAMES SMITH 298 | JOHN SMITH 299 | ROBERT SMITH 300 | MICHAEL SMITH 301 | WILLIAM SMITH 302 | DAVID SMITH 303 | ... 304 | ``` 305 | ### AND & OR Queries 306 | 307 | #### AND Queries 308 | 309 | We can achieve an AND query by simply specifying another field in the project object we pass to the *find()* function. Say that we want to get everyone in the database whose last name is SMITH and first name is JAMES: 310 | 311 | ```js 312 | db.bank_data.find({last_name: "SMITH", first_name: "JAMES"}) 313 | ``` 314 | 315 | We should just get one result if you haven't modified the test data (you can get the pretty JSON formatting by just doing ''[0]" on the collection): 316 | 317 | ```json 318 | { 319 | "_id" : ObjectId("546960b6ca357ca95f30167f"), 320 | "first_name" : "JAMES", 321 | "last_name" : "SMITH", 322 | "accounts" : [ 323 | { 324 | "account_type" : "Savings", 325 | "account_balance" : 8995952.153640702, 326 | "currency" : "PESO" 327 | }, 328 | { 329 | "account_type" : "Checking", 330 | "account_balance" : 3901436.5580737568, 331 | "currency" : "USD" 332 | } 333 | ] 334 | } 335 | ``` 336 | 337 | We can also specify these constraints on embedded collections. 338 | 339 | First, let's look for all Persons whose last name is SMITH *and* have a Savings account: 340 | 341 | ```js 342 | //we know that we have more than 12 elements in the resulting collection 343 | db.bank_data.find({last_name: "SMITH", "accounts.account_type": "Savings" })[12] 344 | ``` 345 | ```json 346 | { 347 | "_id" : ObjectId("546960b6ca357ca95f301691"), 348 | "first_name" : "EDWARD", 349 | "last_name" : "SMITH", 350 | "accounts" : [ 351 | { 352 | "account_type" : "401K", 353 | "account_balance" : 6577381.434625924, 354 | "currency" : "YEN" 355 | }, 356 | { 357 | "account_type" : "Checking", 358 | "account_balance" : 8998935.759297138, 359 | "currency" : "USD" 360 | }, 361 | { 362 | "account_type" : "Investment", 363 | "account_balance" : 588000.4045217587, 364 | "currency" : "YUAN" 365 | }, 366 | { 367 | // This is the embedded document that matched the query 368 | "account_type" : "Savings", 369 | "account_balance" : 6743563.754405159, 370 | "currency" : "YUAN" 371 | }, 372 | { 373 | "account_type" : "401K", 374 | "account_balance" : 8580650.627761671, 375 | "currency" : "POUNDS STERLING" 376 | }, 377 | { 378 | "account_type" : "401K", 379 | "account_balance" : 7687815.685781645, 380 | "currency" : "YEN" 381 | }, 382 | { 383 | "account_type" : "Checking", 384 | "account_balance" : 9128407.633252997, 385 | "currency" : "EURO" 386 | } 387 | ] 388 | } 389 | ``` 390 | 391 | Notice how we retrieve the entire ```accounts``` array even though we only were looking for the element with the ```account_type``` of Savings. The [```$elemMatch```](http://docs.mongodb.org/manual/reference/operator/projection/elemMatch/) projection operator allows us to return just the first element in an array that meets the criteria. 392 | 393 | We can use this operator by passing a second projection object which filters the information returned by MongoDB: 394 | 395 | ```js 396 | 397 | // only get the first matching sub document in the array ''accounts' 398 | db.bank_data.find({last_name: "SMITH", "accounts.account_type": "Savings" }, { first_name: 1, last_name: 1, accounts: { $elemMatch : { 'account_type' : 'Savings' } } } )[12] 399 | ``` 400 | 401 | This will give us something similar to: 402 | 403 | ```json 404 | { 405 | "_id" : ObjectId("546d7827df1e5b91fcb57133"), 406 | "first_name" : "EDWARD", 407 | "last_name" : "SMITH", 408 | "accounts" : [ 409 | { 410 | "account_type" : "Savings", 411 | "account_balance" : 6743563.754405159, 412 | "currency" : "YUAN" 413 | } 414 | ] 415 | } 416 | ``` 417 | 418 | In the query above we get ```first_name```, ```last_name``` and only the first matching ```account```. This is great way to limit the amount of data sent back by MongoDB which could be helpful for performance reasons. 419 | 420 | Note since we are using the same condition for the ```accounts``` field the following query is a short hand equivalent: 421 | 422 | ```js 423 | // only get the first matching sub document in the array ''accounts' 424 | db.bank_data.find({last_name: "SMITH", "accounts.account_type": "Savings" }, { first_name: 1, last_name: 1, 'accounts.$': 1 } )[12] 425 | ``` 426 | 427 | #### OR Queries 428 | 429 | OR queries are slightly different because they require us to use the **$or** operator alias, since the projection object syntax doesn't allow for us to specify it any other way. 430 | 431 | Say that we wanted to get any person whose last name is SMITH or MARTINEZ. This query would look something like: 432 | 433 | ```js 434 | 435 | db.bank_data.find({$or: [ { last_name: "MARTINEZ"}, {last_name: "SMITH"} ]}) 436 | 437 | ``` 438 | 439 | To make your output a little cleaner, lets omit the accounts data: 440 | 441 | ```js 442 | 443 | db.bank_data.find({$or: [ { last_name: "MARTINEZ"}, {last_name: "SMITH"} ]}, {first_name: 1, last_name: 1}) 444 | 445 | ``` 446 | 447 | You should get a bunch of Person documents with either their last name being MARTINEZ or last name being SMITH 448 | 449 | 450 | ```json 451 | 452 | { "_id" : ObjectId("546960b7ca357ca95f3016cf"), "first_name" : "CARLOS", "last_name" : "SMITH" } 453 | { "_id" : ObjectId("546960b7ca357ca95f3016d0"), "first_name" : "RUSSELL", "last_name" : "SMITH" } 454 | { "_id" : ObjectId("546960b7ca357ca95f3016d1"), "first_name" : "BOBBY", "last_name" : "SMITH" } 455 | { "_id" : ObjectId("546960b7ca357ca95f3016d2"), "first_name" : "VICTOR", "last_name" : "SMITH" } 456 | { "_id" : ObjectId("546960b7ca357ca95f3016d3"), "first_name" : "MARTIN", "last_name" : "SMITH" } 457 | { "_id" : ObjectId("546960b7ca357ca95f3016d4"), "first_name" : "ERNEST", "last_name" : "SMITH" } 458 | { "_id" : ObjectId("546960b7ca357ca95f3016d5"), "first_name" : "PHILLIP", "last_name" : "SMITH" } 459 | { "_id" : ObjectId("546960b7ca357ca95f3016d6"), "first_name" : "TODD", "last_name" : "SMITH" } 460 | { "_id" : ObjectId("546960b7ca357ca95f3016d7"), "first_name" : "JESSE", "last_name" : "SMITH" } 461 | { "_id" : ObjectId("546960b7ca357ca95f3016d8"), "first_name" : "CRAIG", "last_name" : "SMITH" } 462 | { "_id" : ObjectId("546960b7ca357ca95f3016d9"), "first_name" : "ALAN", "last_name" : "SMITH" } 463 | { "_id" : ObjectId("546960b7ca357ca95f3016da"), "first_name" : "SHAWN", "last_name" : "SMITH" } 464 | { "_id" : ObjectId("546960b7ca357ca95f3016db"), "first_name" : "CLARENCE", "last_name" : "SMITH" } 465 | { "_id" : ObjectId("546960b7ca357ca95f3016dc"), "first_name" : "SEAN", "last_name" : "SMITH" } 466 | { "_id" : ObjectId("546960b7ca357ca95f3016dd"), "first_name" : "PHILIP", "last_name" : "SMITH" } 467 | { "_id" : ObjectId("546960b7ca357ca95f3016de"), "first_name" : "CHRIS", "last_name" : "SMITH" } 468 | { "_id" : ObjectId("546960b7ca357ca95f3016df"), "first_name" : "JOHNNY", "last_name" : "SMITH" } 469 | { "_id" : ObjectId("546960b7ca357ca95f3016e0"), "first_name" : "EARL", "last_name" : "SMITH" } 470 | { "_id" : ObjectId("546960b7ca357ca95f3016e1"), "first_name" : "JIMMY", "last_name" : "SMITH" } 471 | { "_id" : ObjectId("546960b7ca357ca95f3016e2"), "first_name" : "ANTONIO", "last_name" : "SMITH" } 472 | { "_id" : ObjectId("546960beca357ca95f301a67"), "first_name" : "JAMES", "last_name" : "MARTINEZ" } 473 | { "_id" : ObjectId("546960beca357ca95f301a68"), "first_name" : "JOHN", "last_name" : "MARTINEZ" } 474 | { "_id" : ObjectId("546960beca357ca95f301a69"), "first_name" : "ROBERT", "last_name" : "MARTINEZ" } 475 | { "_id" : ObjectId("546960beca357ca95f301a6a"), "first_name" : "MICHAEL", "last_name" : "MARTINEZ" } 476 | { "_id" : ObjectId("546960beca357ca95f301a6b"), "first_name" : "WILLIAM", "last_name" : "MARTINEZ" } 477 | { "_id" : ObjectId("546960beca357ca95f301a6c"), "first_name" : "DAVID", "last_name" : "MARTINEZ" } 478 | { "_id" : ObjectId("546960beca357ca95f301a6d"), "first_name" : "RICHARD", "last_name" : "MARTINEZ" } 479 | { "_id" : ObjectId("546960beca357ca95f301a6e"), "first_name" : "CHARLES", "last_name" : "MARTINEZ" } 480 | { "_id" : ObjectId("546960beca357ca95f301a6f"), "first_name" : "JOSEPH", "last_name" : "MARTINEZ" } 481 | { "_id" : ObjectId("546960beca357ca95f301a70"), "first_name" : "THOMAS", "last_name" : "MARTINEZ" } 482 | { "_id" : ObjectId("546960beca357ca95f301a71"), "first_name" : "CHRISTOPHER", "last_name" : "MARTINEZ" } 483 | { "_id" : ObjectId("546960beca357ca95f301a72"), "first_name" : "DANIEL", "last_name" : "MARTINEZ" } 484 | { "_id" : ObjectId("546960beca357ca95f301a73"), "first_name" : "PAUL", "last_name" : "MARTINEZ" } 485 | { "_id" : ObjectId("546960beca357ca95f301a74"), "first_name" : "MARK", "last_name" : "MARTINEZ" } 486 | { "_id" : ObjectId("546960beca357ca95f301a75"), "first_name" : "DONALD", "last_name" : "MARTINEZ" } 487 | { "_id" : ObjectId("546960beca357ca95f301a76"), "first_name" : "GEORGE", "last_name" : "MARTINEZ" } 488 | { "_id" : ObjectId("546960beca357ca95f301a77"), "first_name" : "KENNETH", "last_name" : "MARTINEZ" } 489 | { "_id" : ObjectId("546960beca357ca95f301a78"), "first_name" : "STEVEN", "last_name" : "MARTINEZ" } 490 | { "_id" : ObjectId("546960beca357ca95f301a79"), "first_name" : "EDWARD", "last_name" : "MARTINEZ" } 491 | { "_id" : ObjectId("546960beca357ca95f301a7a"), "first_name" : "BRIAN", "last_name" : "MARTINEZ" } 492 | 493 | ``` 494 | 495 | Note that **you may have to type 'it'** to iterate to get to the MARTINEZ results. You can also get the results ordered by first name to see that you are getting both last names by using the **sort()** function on the returned cursor 496 | 497 | ```js 498 | db.bank_data.find({$or: [ { last_name: "MARTINEZ"}, {last_name: "SMITH"} ]}, {first_name: 1, last_name: 1}).sort({first_name: 1 }) 499 | ``` 500 | 501 | The '1' means to sort ascending by the specified column, and '-1' means sort descending. Since these are string fields, you'll get a a nice alphabetical listing descending by first name: 502 | 503 | ```json 504 | { "_id" : ObjectId("546960b6ca357ca95f3016cb"), "first_name" : "AARON", "last_name" : "SMITH" } 505 | { "_id" : ObjectId("546960bfca357ca95f301ab3"), "first_name" : "AARON", "last_name" : "MARTINEZ" } 506 | { "_id" : ObjectId("546960b6ca357ca95f3016c3"), "first_name" : "ADAM", "last_name" : "SMITH" } 507 | { "_id" : ObjectId("546960bfca357ca95f301aab"), "first_name" : "ADAM", "last_name" : "MARTINEZ" } 508 | { "_id" : ObjectId("546960b7ca357ca95f3016d9"), "first_name" : "ALAN", "last_name" : "SMITH" } 509 | { "_id" : ObjectId("546960bfca357ca95f301ac1"), "first_name" : "ALAN", "last_name" : "MARTINEZ" } 510 | { "_id" : ObjectId("546960b6ca357ca95f3016b4"), "first_name" : "ALBERT", "last_name" : "SMITH" } 511 | { "_id" : ObjectId("546960bfca357ca95f301a9c"), "first_name" : "ALBERT", "last_name" : "MARTINEZ" } 512 | { "_id" : ObjectId("546960b6ca357ca95f3016a1"), "first_name" : "ANDREW", "last_name" : "SMITH" } 513 | { "_id" : ObjectId("546960beca357ca95f301a89"), "first_name" : "ANDREW", "last_name" : "MARTINEZ" } 514 | { "_id" : ObjectId("546960b6ca357ca95f301694"), "first_name" : "ANTHONY", "last_name" : "SMITH" } 515 | { "_id" : ObjectId("546960beca357ca95f301a7c"), "first_name" : "ANTHONY", "last_name" : "MARTINEZ" } 516 | { "_id" : ObjectId("546960b7ca357ca95f3016e2"), "first_name" : "ANTONIO", "last_name" : "SMITH" } 517 | { "_id" : ObjectId("546960bfca357ca95f301aca"), "first_name" : "ANTONIO", "last_name" : "MARTINEZ" } 518 | { "_id" : ObjectId("546960b6ca357ca95f3016ae"), "first_name" : "ARTHUR", "last_name" : "SMITH" } 519 | { "_id" : ObjectId("546960bfca357ca95f301a96"), "first_name" : "ARTHUR", "last_name" : "MARTINEZ" } 520 | { "_id" : ObjectId("546960b6ca357ca95f3016c0"), "first_name" : "BENJAMIN", "last_name" : "SMITH" } 521 | { "_id" : ObjectId("546960bfca357ca95f301aa8"), "first_name" : "BENJAMIN", "last_name" : "MARTINEZ" } 522 | { "_id" : ObjectId("546960b6ca357ca95f3016c7"), "first_name" : "BILLY", "last_name" : "SMITH" } 523 | { "_id" : ObjectId("546960bfca357ca95f301aaf"), "first_name" : "BILLY", "last_name" : "MARTINEZ" } 524 | 525 | ``` 526 | ### Greater Than, Less Than, Not Equal To Operators 527 | 528 | Like the **$or** operator alias, mongodb also offers the **$gt**, **$lt**, **$ne** operator aliases for greater than, less than and not equal to operators, respectivley. There are also coorsponding **$gte**, **$lte** for greater than or equal to and less than or equal to. 529 | 530 | Say that we only wanted to retrieve persons with any bank account with an account balance greater than 9 million dollars USD. 531 | 532 | We can do this by using the **$gt** operator on the embedded account document *account_balance* field: 533 | 534 | ```js 535 | db.bank_data.find({ 'accounts.account_balance': {$gt: 9000000} }) 536 | ``` 537 | 538 | Here's the 1000th returned Person document: 539 | 540 | ```json 541 | { 542 | "_id" : ObjectId("546960cbca357ca95f302080"), 543 | "first_name" : "RALPH", 544 | "last_name" : "LEWIS", 545 | "accounts" : [ 546 | { 547 | "account_type" : "Checking", 548 | "account_balance" : 5643915.251352968, 549 | "currency" : "PESO" 550 | }, 551 | { 552 | "account_type" : "Savings", 553 | "account_balance" : 1344242.1501158585, 554 | "currency" : "USD" 555 | }, 556 | { 557 | "account_type" : "Savings", 558 | "account_balance" : 1521705.760721184, 559 | "currency" : "POUNDS STERLING" 560 | }, 561 | { 562 | "account_type" : "401K", 563 | "account_balance" : 9749745.140437951, 564 | "currency" : "YUAN" 565 | }, 566 | { 567 | "account_type" : "Savings", 568 | "account_balance" : 7826270.383932192, 569 | "currency" : "POUNDS STERLING" 570 | } 571 | ] 572 | } 573 | ``` 574 | 575 | This still doesn't get us exactly where we want to be just yet since we aren't taking into consideration the *currency* field. It isn't accurate to query by just the account balance because different currencies are worth different amounts. We can combine $gt operator with an **and** operation by just specifying the second field in the sub document: 576 | 577 | ```js 578 | db.bank_data.find({ 'accounts.account_balance': {$gt: 9000000}, 'accounts.currency': 'USD' }) 579 | ``` 580 | 581 | Although this seems correct its actually subtly inaccurate. This query will return Persons with an account that has at least 9 Million and an account that has a currency type of USD. Unfortunatley that's not what we were looking for. 582 | 583 | This problem can be solved with the [```$elemMatch```](http://docs.mongodb.org/manual/reference/operator/query/elemMatch/) query operator which can be used to match a specific element in an array embedded in the document. This operator works very similar to the [projection version](http://docs.mongodb.org/manual/reference/operator/query/elemMatch/) with the exception that it is used as part of a query and not a projection. 584 | 585 | Here's how we can use the operator to find a Persons with an account balance of $9 USD: 586 | 587 | ```js 588 | db.bank_data.find({ accounts: { $elemMatch : { "account_type": "Checking", "currency": "USD", 'account_balance' : { $gt: 9900000 } } } } ) 589 | ``` 590 | 591 | Now you can see that we are only selecting Persons with USD bank accounts greater than 9 million dollars. 592 | 593 | ```json 594 | { 595 | "_id" : ObjectId("546960b7ca357ca95f301732"), 596 | "first_name" : "EUGENE", 597 | "last_name" : "JOHNSON", 598 | "accounts" : [ 599 | { 600 | "account_type" : "Savings", 601 | "account_balance" : 9644738.165106645, 602 | "currency" : "YUAN" 603 | }, 604 | { 605 | "account_type" : "Investment", 606 | "account_balance" : 3382188.763320642, 607 | "currency" : "YUAN" 608 | }, 609 | { 610 | "account_type" : "Checking", 611 | "account_balance" : 7265775.6412804155, 612 | "currency" : "POUNDS STERLING" 613 | }, 614 | { 615 | "account_type" : "401K", 616 | "account_balance" : 4662322.562082556, 617 | "currency" : "YEN" 618 | }, 619 | { 620 | "account_type" : "Checking", 621 | "account_balance" : 1585816.9293256353, 622 | "currency" : "USD" 623 | }, 624 | { 625 | /////////////////////////////////////////////////////// 626 | // This is the matching document 627 | /////////////////////////////////////////////////////// 628 | "account_type" : "Checking", 629 | "account_balance" : 9512844.082029575, 630 | "currency" : "USD" 631 | } 632 | ] 633 | } 634 | 635 | ``` 636 | 637 | What if the bank wanted to exclude all persons with a checking account from this query. We can do this by adding the **$ne** into the $elemMatch operator alias: 638 | 639 | ```js 640 | db.bank_data.find({ 'accounts.account_balance': {$gt: 9000000}, 'accounts.currency': 'USD', 'accounts.account_type': {$ne: 'Checking' } }) 641 | ``` 642 | 643 | This query will exclude *any* person with a checking account regardless of balance. In the sample of documents received, note there are no Checking accounts: 644 | 645 | ```json 646 | { "_id" : ObjectId("546960baca357ca95f301836"), "first_name" : "DENNIS", "last_name" : "JONES", "accounts" : [ { "account_type" : "Investment", "account_balance" : 1663319.9657335512, "currency" : "PESO" }, { "account_type" : "Savings", "account_balance" : 9165545.972862184, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 587530.2496500439, "currency" : "POUNDS STERLING" }, { "account_type" : "Savings", "account_balance" : 4968418.510649419, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 9953368.745059764, "currency" : "PESO" } ] } 647 | { "_id" : ObjectId("546960baca357ca95f30183e"), "first_name" : "ARTHUR", "last_name" : "JONES", "accounts" : [ { "account_type" : "Investment", "account_balance" : 3257180.6435127337, "currency" : "POUNDS STERLING" }, { "account_type" : "Investment", "account_balance" : 4662125.037897458, "currency" : "PESO" }, { "account_type" : "Investment", "account_balance" : 9825512.559612762, "currency" : "EURO" }, { "account_type" : "401K", "account_balance" : 7437629.959444035, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 6814759.514081009, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 8037030.051490649, "currency" : "YEN" }, { "account_type" : "401K", "account_balance" : 4450354.054241277, "currency" : "USD" } ] } 648 | { "_id" : ObjectId("546960baca357ca95f301846"), "first_name" : "JUSTIN", "last_name" : "JONES", "accounts" : [ { "account_type" : "401K", "account_balance" : 5565130.27981727, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 7471462.034394771, "currency" : "PESO" }, { "account_type" : "401K", "account_balance" : 3355240.8867829638, "currency" : "YUAN" }, { "account_type" : "401K", "account_balance" : 8534122.932381403, "currency" : "YEN" }, { "account_type" : "401K", "account_balance" : 1390575.4528828736, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 7442115.797576328, "currency" : "EURO" }, { "account_type" : "401K", "account_balance" : 9704565.387666339, "currency" : "YEN" }, { "account_type" : "401K", "account_balance" : 7691654.466665171, "currency" : "USD" } ] } 649 | ``` 650 | 651 | If we wanted to see how many People had a $9 Million USD account that *wasn't* a checking account we would have to throw in the $ne operator within the $elemMatch operator from above like so: 652 | 653 | ```js 654 | db.bank_data.find({ accounts: { $elemMatch : { "account_type": {$ne: "Checking"}, "currency": "USD", 'account_balance' : { $gt: 9900000 } } } } ) 655 | ``` 656 | Now you can see we have some Person documents with checking accounts but none with balances greater than $9.9M USD: 657 | 658 | ```json 659 | 660 | { "_id" : ObjectId("546d782adf1e5b91fcb57233"), "first_name" : "LOUIS", "last_name" : "WILLIAMS", "accounts" : [ { "account_type" : "401K", "account_balance" : 6706903.630263763, "currency" : "PESO" }, { "account_type" : "Checking", "account_balance" : 718301.4651508627, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 7312210.597896284, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 5729521.857385723, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 4633504.068461469, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 9904890.704406753, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 7627857.810319329, "currency" : "POUNDS STERLING" } ] } 661 | { "_id" : ObjectId("546d782bdf1e5b91fcb57259"), "first_name" : "PAUL", "last_name" : "BROWN", "accounts" : [ { "account_type" : "Savings", "account_balance" : 3600730.92475014, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 9981281.53222422, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 4150310.5143678905, "currency" : "POUNDS STERLING" }, { "account_type" : "Investment", "account_balance" : 1399256.221257143, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 1922134.0013783542, "currency" : "POUNDS STERLING" }, { "account_type" : "Investment", "account_balance" : 851790.2540412813, "currency" : "USD" }, { "account_type" : "Checking", "account_balance" : 2640154.7193671735, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 7269654.143067777, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 7673523.203527218, "currency" : "USD" } ] } 662 | { "_id" : ObjectId("546d782bdf1e5b91fcb5725c"), "first_name" : "GEORGE", "last_name" : "BROWN", "accounts" : [ { "account_type" : "Investment", "account_balance" : 3591667.0242768256, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 9936431.774947472, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 4755925.989557322, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 111172.67009143182, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 332127.87410061574, "currency" : "YEN" }, { "account_type" : "Checking", "account_balance" : 8336491.214461608, "currency" : "USD" } ] } 663 | { "_id" : ObjectId("546d7831df1e5b91fcb57472"), "first_name" : "ROGER", "last_name" : "RODRIGUEZ", "accounts" : [ { "account_type" : "401K", "account_balance" : 1266182.2247735274, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 5380558.306134206, "currency" : "EURO" }, { "account_type" : "401K", "account_balance" : 966932.4347529653, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 4133008.6777187213, "currency" : "PESO" }, { "account_type" : "Investment", "account_balance" : 6284793.329122837, "currency" : "YUAN" }, { "account_type" : "401K", "account_balance" : 2139621.0722251926, "currency" : "POUNDS STERLING" }, { "account_type" : "Savings", "account_balance" : 7236738.633793805, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 9937092.855584502, "currency" : "USD" } ] } 664 | { "_id" : ObjectId("546d7832df1e5b91fcb574bb"), "first_name" : "KEVIN", "last_name" : "WILSON", "accounts" : [ { "account_type" : "Checking", "account_balance" : 5542924.895261332, "currency" : "EURO" }, { "account_type" : "Checking", "account_balance" : 7535244.4205518905, "currency" : "POUNDS STERLING" }, { "account_type" : "Investment", "account_balance" : 5129918.606652998, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 1153817.49683039, "currency" : "PESO" }, { "account_type" : "Investment", "account_balance" : 9286205.466278996, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 9912807.96529748, "currency" : "USD" }, { "account_type" : "Checking", "account_balance" : 8471927.417287258, "currency" : "USD" }, { "account_type" : "Checking", "account_balance" : 568263.1176739989, "currency" : "PESO" }, { "account_type" : "Savings", "account_balance" : 3955929.3703504615, "currency" : "YUAN" } ] } 665 | { "_id" : ObjectId("546d7835df1e5b91fcb575c8"), "first_name" : "SHAWN", "last_name" : "ANDERSON", "accounts" : [ { "account_type" : "401K", "account_balance" : 1735822.894719818, "currency" : "POUNDS STERLING" }, { "account_type" : "Savings", "account_balance" : 69463.06213872484, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 8474192.558871966, "currency" : "PESO" }, { "account_type" : "Investment", "account_balance" : 9975197.640174257, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 9454529.585621798, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 8932461.564786868, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 7886462.058590259, "currency" : "PESO" } ] } 666 | { "_id" : ObjectId("546d7838df1e5b91fcb576f6"), "first_name" : "SEAN", "last_name" : "HERNANDEZ", "accounts" : [ { "account_type" : "Savings", "account_balance" : 372651.3730239677, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 9915611.439216157, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 9183270.066467846, "currency" : "YEN" }, { "account_type" : "Checking", "account_balance" : 3186223.8262610394, "currency" : "PESO" } ] } 667 | { "_id" : ObjectId("546d7838df1e5b91fcb57729"), "first_name" : "DOUGLAS", "last_name" : "MOORE", "accounts" : [ { "account_type" : "Savings", "account_balance" : 9930827.898145996, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 963529.2124392728, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 2086876.6013749957, "currency" : "POUNDS STERLING" } ] } 668 | { "_id" : ObjectId("546d7839df1e5b91fcb577a7"), "first_name" : "FRED", "last_name" : "MARTIN", "accounts" : [ { "account_type" : "401K", "account_balance" : 5553989.052907477, "currency" : "PESO" }, { "account_type" : "Investment", "account_balance" : 4578506.179048301, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 5079883.609015118, "currency" : "PESO" }, { "account_type" : "Savings", "account_balance" : 1084537.3091741293, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 6991969.760733552, "currency" : "YUAN" }, { "account_type" : "401K", "account_balance" : 9935860.559944985, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 9163022.170428082, "currency" : "PESO" }, { "account_type" : "Checking", "account_balance" : 1017089.2610129539, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 3803795.491410911, "currency" : "EURO" } ] } 669 | { "_id" : ObjectId("546d783adf1e5b91fcb577e6"), "first_name" : "STEPHEN", "last_name" : "JACKSON", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9976366.179805, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 634648.950635531, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 6826830.6245790515, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 804466.2337015264, "currency" : "USD" }, { "account_type" : "Checking", "account_balance" : 5790946.209525525, "currency" : "YEN" } ] } 670 | { "_id" : ObjectId("546d783cdf1e5b91fcb578b9"), "first_name" : "DOUGLAS", "last_name" : "WHITE", "accounts" : [ { "account_type" : "Savings", "account_balance" : 3693157.710088576, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 1204302.2580342523, "currency" : "YEN" }, { "account_type" : "Checking", "account_balance" : 9397896.361452024, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 6319674.236169158, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 8952952.133197326, "currency" : "POUNDS STERLING" }, { "account_type" : "Checking", "account_balance" : 9154474.434485374, "currency" : "YUAN" }, { "account_type" : "Investment", "account_balance" : 4039387.780962508, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 2161016.8604762834, "currency" : "EURO" }, { "account_type" : "401K", "account_balance" : 9924368.37347127, "currency" : "USD" } ] } 671 | { "_id" : ObjectId("546d783ddf1e5b91fcb578e5"), "first_name" : "JESSE", "last_name" : "WHITE", "accounts" : [ { "account_type" : "Checking", "account_balance" : 5895330.511958937, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 7371419.86004984, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 9744478.560699593, "currency" : "YEN" }, { "account_type" : "401K", "account_balance" : 9971537.906037796, "currency" : "USD" }, { "account_type" : "Checking", "account_balance" : 9821381.550689302, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 4632305.398220146, "currency" : "POUNDS STERLING" } ] } 672 | { "_id" : ObjectId("546d783edf1e5b91fcb57952"), "first_name" : "EARL", "last_name" : "LOPEZ", "accounts" : [ { "account_type" : "Savings", "account_balance" : 336681.4217056185, "currency" : "POUNDS STERLING" }, { "account_type" : "Investment", "account_balance" : 9301992.334617374, "currency" : "POUNDS STERLING" }, { "account_type" : "Checking", "account_balance" : 9239927.854268068, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 4747225.807765926, "currency" : "POUNDS STERLING" }, { "account_type" : "401K", "account_balance" : 823268.2376189504, "currency" : "YEN" }, { "account_type" : "Checking", "account_balance" : 1940151.4545807643, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 8428993.092331726, "currency" : "POUNDS STERLING" }, { "account_type" : "Investment", "account_balance" : 7421421.446493696, "currency" : "YUAN" }, { "account_type" : "Investment", "account_balance" : 9985971.946981102, "currency" : "USD" } ] } 673 | { "_id" : ObjectId("546d7840df1e5b91fcb57a40"), "first_name" : "RAYMOND", "last_name" : "HARRIS", "accounts" : [ { "account_type" : "401K", "account_balance" : 6854957.208460663, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 9985498.739699954, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 2405508.921211977, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 5133962.469403559, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 197103.2017247777, "currency" : "PESO" }, { "account_type" : "Checking", "account_balance" : 5311800.366872663, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 8919230.848368987, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 4527659.2591276765, "currency" : "EURO" }, { "account_type" : "Investment", "account_balance" : 1140229.1083418014, "currency" : "POUNDS STERLING" } ] } 674 | { "_id" : ObjectId("546d7841df1e5b91fcb57aa2"), "first_name" : "STEPHEN", "last_name" : "CLARK", "accounts" : [ { "account_type" : "Investment", "account_balance" : 5263399.940306952, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 9967826.839734461, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 4631496.407274911, "currency" : "YEN" }, { "account_type" : "Checking", "account_balance" : 6080809.13739095, "currency" : "YEN" } ] } 675 | { "_id" : ObjectId("546d7843df1e5b91fcb57b78"), "first_name" : "ARTHUR", "last_name" : "ROBINSON", "accounts" : [ { "account_type" : "Checking", "account_balance" : 1357467.3205083625, "currency" : "PESO" }, { "account_type" : "Checking", "account_balance" : 2643084.4736294234, "currency" : "EURO" }, { "account_type" : "Checking", "account_balance" : 8593704.150764225, "currency" : "PESO" }, { "account_type" : "Checking", "account_balance" : 4838948.93706009, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 7162944.7032554, "currency" : "YUAN" }, { "account_type" : "Investment", "account_balance" : 9910377.96566371, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 3883087.065123636, "currency" : "YEN" }, { "account_type" : "401K", "account_balance" : 7638535.089621747, "currency" : "USD" }, { "account_type" : "Checking", "account_balance" : 5357708.06690717, "currency" : "POUNDS STERLING" } ] } 676 | { "_id" : ObjectId("546d7845df1e5b91fcb57bf1"), "first_name" : "ADAM", "last_name" : "WALKER", "accounts" : [ { "account_type" : "401K", "account_balance" : 8845986.889367267, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 7872933.596046742, "currency" : "YEN" }, { "account_type" : "Savings", "account_balance" : 3972322.2898087455, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 6644355.511821516, "currency" : "PESO" }, { "account_type" : "Savings", "account_balance" : 9944452.997038499, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 7315829.963859785, "currency" : "EURO" }, { "account_type" : "401K", "account_balance" : 1500268.200328492, "currency" : "USD" }, { "account_type" : "Investment", "account_balance" : 1899574.9145137856, "currency" : "YEN" }, { "account_type" : "Investment", "account_balance" : 1466540.1610838561, "currency" : "POUNDS STERLING" } ] } 677 | { "_id" : ObjectId("546d7847df1e5b91fcb57c5d"), "first_name" : "AARON", "last_name" : "PEREZ", "accounts" : [ { "account_type" : "Investment", "account_balance" : 5799973.474100724, "currency" : "EURO" }, { "account_type" : "Savings", "account_balance" : 9907659.889359972, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 5076597.758945461, "currency" : "YUAN" }, { "account_type" : "Savings", "account_balance" : 1661545.5589190929, "currency" : "PESO" }, { "account_type" : "Savings", "account_balance" : 707982.6495432614, "currency" : "YUAN" }, { "account_type" : "Investment", "account_balance" : 7514690.33361989, "currency" : "PESO" }, { "account_type" : "401K", "account_balance" : 6000364.979929898, "currency" : "PESO" }, { "account_type" : "Investment", "account_balance" : 6631186.570023831, "currency" : "EURO" }, { "account_type" : "Investment", "account_balance" : 8096845.241363882, "currency" : "POUNDS STERLING" } ] } 678 | { "_id" : ObjectId("546d7848df1e5b91fcb57cb0"), "first_name" : "SAMUEL", "last_name" : "HALL", "accounts" : [ { "account_type" : "Savings", "account_balance" : 7145237.715715418, "currency" : "USD" }, { "account_type" : "Checking", "account_balance" : 1164475.4884442165, "currency" : "YUAN" }, { "account_type" : "Checking", "account_balance" : 2042413.7690080977, "currency" : "YUAN" }, { "account_type" : "401K", "account_balance" : 9909034.04869648, "currency" : "USD" } ] } 679 | { "_id" : ObjectId("546d7849df1e5b91fcb57d30"), "first_name" : "TODD", "last_name" : "YOUNG", "accounts" : [ { "account_type" : "401K", "account_balance" : 5602774.185507225, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 9916627.537654825, "currency" : "USD" }, { "account_type" : "Savings", "account_balance" : 545377.3508226005, "currency" : "EURO" }, { "account_type" : "401K", "account_balance" : 6689640.075625194, "currency" : "USD" }, { "account_type" : "401K", "account_balance" : 9933399.766133368, "currency" : "USD" } ] } 680 | ``` 681 | 682 | We can also order our query by descending account balance with the **sort()** function like we did previously: 683 | 684 | ```js 685 | db.bank_data.find({ accounts: { $elemMatch : { "account_type": {$ne: "Checking"}, "currency": "USD", 'account_balance' : { $gt: 9900000 } } } } ).sort({ "accounts.account_balance": -1 }) 686 | ``` 687 | 688 | To make the output cleaner we can use a projection object with the $ operator: 689 | 690 | ```js 691 | db.bank_data.find({ accounts: { $elemMatch : { "account_type": {$ne: "Checking"}, "currency": "USD", 'account_balance' : { $gt: 9900000 } } } }, { 'accounts.$' : 1, first_name: 1, last_name: 1} ).sort({ 'accounts.account_balance': -1 }) 692 | ``` 693 | 694 | ```json 695 | { "_id" : ObjectId("546d785bdf1e5b91fcb58427"), "first_name" : "FRED", "last_name" : "TURNER", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9999788.563028697, "currency" : "USD" } ] } 696 | { "_id" : ObjectId("546d796adf1e5b91fcb6314b"), "first_name" : "PHILIP", "last_name" : "LINDSEY", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9999072.08500216, "currency" : "USD" } ] } 697 | { "_id" : ObjectId("546d792ddf1e5b91fcb5e4d9"), "first_name" : "MATTHEW", "last_name" : "WADE", "accounts" : [ { "account_type" : "Savings", "account_balance" : 9998874.50726602, "currency" : "USD" } ] } 698 | { "_id" : ObjectId("546d7894df1e5b91fcb59a99"), "first_name" : "KENNETH", "last_name" : "HAMILTON", "accounts" : [ { "account_type" : "401K", "account_balance" : 9998709.970523216, "currency" : "USD" } ] } 699 | { "_id" : ObjectId("546d7891df1e5b91fcb5997a"), "first_name" : "JEFFREY", "last_name" : "PATTERSON", "accounts" : [ { "account_type" : "401K", "account_balance" : 9997402.014245303, "currency" : "USD" } ] } 700 | { "_id" : ObjectId("546d7882df1e5b91fcb59313"), "first_name" : "ALAN", "last_name" : "FOSTER", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9997178.09638108, "currency" : "USD" } ] } 701 | { "_id" : ObjectId("546d7962df1e5b91fcb61754"), "first_name" : "ARTHUR", "last_name" : "MALONE", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9997177.821640948, "currency" : "USD" } ] } 702 | { "_id" : ObjectId("546d7969df1e5b91fcb62bd1"), "first_name" : "CLARENCE", "last_name" : "GIBBS", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9997139.50004914, "currency" : "USD" } ] } 703 | { "_id" : ObjectId("546d795ddf1e5b91fcb61158"), "first_name" : "GEORGE", "last_name" : "BRADY", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9997094.69878117, "currency" : "USD" } ] } 704 | { "_id" : ObjectId("546d7934df1e5b91fcb5ea09"), "first_name" : "JACK", "last_name" : "RHODES", "accounts" : [ { "account_type" : "401K", "account_balance" : 9996803.825815447, "currency" : "USD" } ] } 705 | { "_id" : ObjectId("546d786fdf1e5b91fcb58bb8"), "first_name" : "CHARLES", "last_name" : "KELLY", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9996786.617304295, "currency" : "USD" } ] } 706 | { "_id" : ObjectId("546d78e0df1e5b91fcb5bad2"), "first_name" : "BENJAMIN", "last_name" : "SPENCER", "accounts" : [ { "account_type" : "401K", "account_balance" : 9996443.450581236, "currency" : "USD" } ] } 707 | { "_id" : ObjectId("546d78f0df1e5b91fcb5c23d"), "first_name" : "ROY", "last_name" : "RAY", "accounts" : [ { "account_type" : "401K", "account_balance" : 9995897.143798517, "currency" : "USD" } ] } 708 | { "_id" : ObjectId("546d793edf1e5b91fcb5f1ca"), "first_name" : "JOSHUA", "last_name" : "SCHWARTZ", "accounts" : [ { "account_type" : "Savings", "account_balance" : 9995584.289293924, "currency" : "USD" } ] } 709 | { "_id" : ObjectId("546d796adf1e5b91fcb632c3"), "first_name" : "FRED", "last_name" : "OWEN", "accounts" : [ { "account_type" : "401K", "account_balance" : 9995557.60690483, "currency" : "USD" } ] } 710 | { "_id" : ObjectId("546d785adf1e5b91fcb583af"), "first_name" : "JOE", "last_name" : "EVANS", "accounts" : [ { "account_type" : "Investment", "account_balance" : 9995518.07925041, "currency" : "USD" } ] } 711 | { "_id" : ObjectId("546d78bddf1e5b91fcb5ab67"), "first_name" : "EDWARD", "last_name" : "SHAW", "accounts" : [ { "account_type" : "401K", "account_balance" : 9995391.989827948, "currency" : "USD" } ] } 712 | { "_id" : ObjectId("546d789ddf1e5b91fcb59df0"), "first_name" : "WAYNE", "last_name" : "WEST", "accounts" : [ { "account_type" : "Savings", "account_balance" : 9995363.14444239, "currency" : "USD" } ] } 713 | { "_id" : ObjectId("546d789edf1e5b91fcb59e0c"), "first_name" : "ANTONIO", "last_name" : "WEST", "accounts" : [ { "account_type" : "401K", "account_balance" : 9995329.709965305, "currency" : "USD" } ] } 714 | { "_id" : ObjectId("546d7946df1e5b91fcb5f869"), "first_name" : "ERIC", "last_name" : "THORNTON", "accounts" : [ { "account_type" : "Savings", "account_balance" : 9995327.38864402, "currency" : "USD" } ] } 715 | ``` 716 | 717 | ## Conclusion 718 | 719 | In this section we covered how to get mongodb up and running your machine as well as how to go about doing simple queries from the interactive shell. 720 | 721 | MongoDB has a unique querying interface where a *query* object is specified which can contain operators and selects which fields should be used to match documents in the collection. We can chain these queries with the **sort()** function to return our documents in any particular order we need. In addition we can specify a second *projection* object to specify only the fields in the document should be included in the results. 722 | 723 | Module 3 will dive into the Node.js and the C# language drivers and demonstrate how we can create and update Person entities in the database. 724 | -------------------------------------------------------------------------------- /module2_getting_started/ScreenShots/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module2_getting_started/ScreenShots/.DS_Store -------------------------------------------------------------------------------- /module2_getting_started/ScreenShots/mongodbss1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module2_getting_started/ScreenShots/mongodbss1.png -------------------------------------------------------------------------------- /module2_getting_started/ScreenShots/mongodbss2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module2_getting_started/ScreenShots/mongodbss2.png -------------------------------------------------------------------------------- /module2_getting_started/bank_data.json.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module2_getting_started/bank_data.json.zip -------------------------------------------------------------------------------- /module3_language_drivers/CSharpEnd/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpEnd/MongoSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547} 8 | Exe 9 | Properties 10 | MongoSample 11 | MongoSample 12 | v4.5.1 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | packages\mongocsharpdriver.1.9.2\lib\net35\MongoDB.Bson.dll 38 | 39 | 40 | packages\mongocsharpdriver.1.9.2\lib\net35\MongoDB.Driver.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpEnd/MongoSample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoSample", "MongoSample.csproj", "{2CC8B57B-B0F8-4268-9E76-F9B8A421D547}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpEnd/Program.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson; 2 | using MongoDB.Driver; 3 | using MongoDB.Driver.Builders; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace MongoSample 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | MongoClient client = new MongoClient("mongodb://127.0.0.1:27017/test"); // connect to localhost 17 | MongoServer server = client.GetServer(); 18 | 19 | MongoDatabase database = server.GetDatabase("test"); // "test" is the name of the database 20 | MongoCollection bankData = database.GetCollection("bank_data"); 21 | BsonDocument person = new BsonDocument { 22 | { "first_name", "Steven"}, 23 | { "last_name", "Edouard"}, 24 | { "accounts", new BsonArray { 25 | new BsonDocument { 26 | { "account_balance", 50000000}, 27 | { "account_type", "Investment"}, 28 | { "currency", "USD"} 29 | } 30 | }} 31 | }; 32 | bankData.Insert(person); 33 | System.Console.WriteLine(person["_id"]); 34 | 35 | //increment this persons balance by 100000 36 | person["accounts"][0]["account_balance"] = person["accounts"][0]["account_balance"].AsInt32 + 100000; 37 | bankData.Save(person); 38 | System.Console.WriteLine("Successfully updated 1 document."); 39 | 40 | //retrieve the inserted collection from mongodb 41 | //should be the exact same object we just updated 42 | BsonDocument newPerson = bankData.FindOneById(person["_id"]); 43 | //check if the account balance was updated. 44 | System.Console.WriteLine(newPerson["accounts"][0]["account_balance"].AsInt32); 45 | 46 | 47 | 48 | //now delete the document we just inserted 49 | var query = Query.EQ("_id", newPerson["_id"]); 50 | WriteConcernResult result = bankData.Remove(query); 51 | System.Console.WriteLine("number of documents removed: " + result.DocumentsAffected); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpEnd/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MongoSample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MongoSample")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("abae78da-3506-450b-9508-42a938c86575")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpEnd/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpStart/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpStart/MongoSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547} 8 | Exe 9 | Properties 10 | MongoSample 11 | MongoSample 12 | v4.5.1 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | packages\mongocsharpdriver.1.9.2\lib\net35\MongoDB.Bson.dll 38 | 39 | 40 | packages\mongocsharpdriver.1.9.2\lib\net35\MongoDB.Driver.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpStart/MongoSample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoSample", "MongoSample.csproj", "{2CC8B57B-B0F8-4268-9E76-F9B8A421D547}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {2CC8B57B-B0F8-4268-9E76-F9B8A421D547}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpStart/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MongoSample 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpStart/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MongoSample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MongoSample")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("abae78da-3506-450b-9508-42a938c86575")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /module3_language_drivers/CSharpStart/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /module3_language_drivers/End/app.js: -------------------------------------------------------------------------------- 1 | // import the language driver 2 | var MongoClient = require('mongodb').MongoClient 3 | , assert = require('assert'); 4 | var ObjectID = require('mongodb').ObjectID; 5 | 6 | // Connection URL for local mongodb server 7 | var url = 'mongodb://127.0.0.1:27017/test'; 8 | 9 | // Use connect method to connect to the Server 10 | MongoClient.connect(url, function(err, db) { 11 | 12 | //ensure we've connected 13 | assert.equal(null, err); 14 | 15 | var bankData = db.collection('bank_data'); 16 | 17 | bankData.insert({ 18 | first_name: "Steven", 19 | last_name: "Edouard", 20 | accounts: [ 21 | { 22 | account_balance: "50000000", 23 | account_type: "Investment", 24 | currency: "USD" 25 | }] 26 | }, function(err, result){ 27 | 28 | if(err){ 29 | return console.error(err); 30 | } 31 | 32 | console.log('inserted: '); 33 | console.log(result); 34 | console.log('inserted ' + result.length + ' docs'); 35 | 36 | var updatedPerson = result[0]; 37 | updatedPerson.accounts[0].account_balance += 100000; 38 | 39 | bankData.update( { _id: new ObjectID(result[0]._id )}, updatedPerson, {w: 1}, function(err, count){ 40 | 41 | if(err){ 42 | return console.error(err); 43 | } 44 | 45 | console.log('sucessfully updated ' + count + ' person documents'); 46 | 47 | //retrieve the inserted collection from mongodb 48 | //should be the exact same object we just updated 49 | 50 | bankData.findOne({_id: new ObjectID(result[0]._id)}, function(err,doc){ 51 | 52 | if(err){ 53 | return console.error(err); 54 | } 55 | 56 | console.log('retrieved Person ' + doc.first_name + ' ' + doc.last_name); 57 | console.log('accounts: '); 58 | for(var i in doc.accounts){ 59 | console.log('Type: ' + doc.accounts[i].account_type); 60 | console.log('Balance: ' + doc.accounts[i].account_balance); 61 | } 62 | 63 | //now delete the document we just inserted 64 | 65 | bankData.remove({_id: new ObjectID(result[0]._id)}, function(err,count){ 66 | 67 | if(err){ 68 | db.close(); 69 | return console.error(err); 70 | } 71 | 72 | console.log('sucessfully deleted ' + count + ' documents'); 73 | 74 | return db.close(); 75 | }); 76 | 77 | 78 | }); 79 | }); 80 | 81 | 82 | 83 | return; 84 | 85 | }); 86 | 87 | 88 | 89 | return console.log("Connected correctly to server"); 90 | 91 | }); -------------------------------------------------------------------------------- /module3_language_drivers/End/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongodb-mva-nodejs", 3 | "version": "1.0.0", 4 | "description": "generates a test json file for use by mongodb", 5 | "main": "app.js", 6 | "dependencies": { 7 | "async": "^0.9.0", 8 | "mongodb": "^1.4.20" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /module3_language_drivers/README.md: -------------------------------------------------------------------------------- 1 | # Module 3: MongoDB Node.js and C# Language Drivers 2 | 3 | # Objectives 4 | 5 | By the end of this section you will know how to: 6 | 7 | - Connect a Node.js and C# application to MongoDB using a language driver 8 | - Perform Create Read Update and Delete (CRUD) operations on a MongoDB collection from Node.js and C# 9 | 10 | # Introduction 11 | 12 | Every database has language drivers that allow you to interact with the database from a particular programming language. In this module we will use the Node.js and C# language drivers which allow us to do pretty much everything we are able to on the Mongo Interactive Shell but from our application. 13 | 14 | 15 | # Node.js 16 | 17 | ## Getting Started 18 | 19 | To install the MongoDB driver for Node.js execute the following command in the [Start](./Start) directory of this folder. Ensure you have [node.js installed](http://nodejs.org) 20 | 21 | ```batch 22 | npm install 23 | ``` 24 | 25 | Because ```package.json``` contains the reference to the mongodb language driver, it gets installed as part of this command. 26 | 27 | Now, let's take a look at our starter code within ```app.js```: 28 | 29 | ```js 30 | // import the language driver 31 | var MongoClient = require('mongodb').MongoClient 32 | , assert = require('assert'); 33 | var ObjectID = require('mongodb').ObjectID; 34 | // Connection URL 35 | var url = 'mongodb://127.0.0.1:27017/test'; 36 | 37 | // Use connect method to connect to the Server 38 | MongoClient.connect(url, function(err, db) { 39 | 40 | //ensure we've connected 41 | assert.equal(null, err); 42 | 43 | 44 | console.log("Connected correctly to server"); 45 | 46 | 47 | //close the database connection 48 | return db.close(); 49 | 50 | }); 51 | ``` 52 | 53 | Running sample above by executing the command: 54 | 55 | ```batch 56 | node app.js 57 | ``` 58 | 59 | (note: on some systems like Ubuntu the node binary is called 'nodejs'') 60 | 61 | The output should indicate a successful connection to your local mongodb server: 62 | 63 | ``` 64 | Connected correctly to server 65 | ``` 66 | 67 | ## Inserting a new Document 68 | Now that we can connect to the server lets try inserting a new document into the Person collection. To begin interacting with our Person collection, we'll need to first request the collection reference from the db object. 69 | 70 | ```js 71 | var bankData = db.collection('bank_data'); 72 | ``` 73 | 74 | Then we can start inserting into this collection reference by simply specifying the object to be inserted into the collection: 75 | 76 | ``` 77 | 78 | bankData.insert({ 79 | first_name: "Steven", 80 | last_name: "Edouard", 81 | accounts: [ 82 | { 83 | account_balance: "50000000", 84 | account_type: "Investment", 85 | currency: "USD" 86 | }] 87 | }) 88 | 89 | ``` 90 | 91 | Finally because Node.js is completely asynchronous, we'll have to add a callback which will be executed once the insert is completed: 92 | 93 | ```js 94 | 95 | bankData.insert({ 96 | first_name: "Steven", 97 | last_name: "Edouard", 98 | accounts: [ 99 | { 100 | account_balance: "50000000", 101 | account_type: "Investment", 102 | currency: "USD" 103 | }] 104 | }, function(err, result){ 105 | if(err){ 106 | return console.error(err); 107 | } 108 | 109 | console.log('inserted: '); 110 | console.log(result); 111 | return console.log('inserted ' + result.length + ' docs'); 112 | }) 113 | 114 | ``` 115 | 116 | Putting everything together to insert the document to our collection: 117 | 118 | ```js 119 | // import the language driver 120 | var MongoClient = require('mongodb').MongoClient 121 | , assert = require('assert'); 122 | // Connection URL for local mongodb server 123 | var url = 'mongodb://127.0.0.1:27017/test'; 124 | 125 | // Use connect method to connect to the Server 126 | MongoClient.connect(url, function(err, db) { 127 | 128 | //ensure we've connected 129 | assert.equal(null, err); 130 | 131 | var bankData = db.collection('bank_data'); 132 | 133 | //insert new document to bank_data collection 134 | bankData.insert({ 135 | first_name: "Steven", 136 | last_name: "Edouard", 137 | accounts: [ 138 | { 139 | account_balance: "50000000", 140 | account_type: "Investment", 141 | currency: "USD" 142 | }] 143 | }, function(err, result){ 144 | //callback is executed after mongodb confirms insert 145 | if(err){ 146 | return console.error(err); 147 | } 148 | 149 | console.log('inserted: '); 150 | console.log(result); 151 | console.log('inserted ' + result.length + ' docs'); 152 | 153 | return db.close(); 154 | 155 | }); 156 | }); 157 | ``` 158 | 159 | Running the above code against your database should result in output similar to the following snippet: 160 | 161 | ``` 162 | Connected correctly to server 163 | inserted: 164 | [ { first_name: 'Steven', 165 | last_name: 'Edouard', 166 | accounts: [ [Object] ], 167 | _id: 5469be33814972ee25b0aa9d } ] 168 | inserted 1 docs 169 | ``` 170 | 171 | ## Updating a stored document 172 | 173 | We've successfully uploaded a person document, now let's modify the existing document that we've inserted. The above code returns the inserted document upon insert so all we need to to is use the **update** function to update the document in the database. 174 | 175 | ```js 176 | 177 | var updatedPerson = result[0]; 178 | //increment this persons balance by 100000 179 | updatedPerson.accounts[0].account_balance += 100000; 180 | 181 | bankData.update( { _id: new ObjectID(updatedPerson._id )}, updatedPerson, {w: 1}, function(err, count){ 182 | if(err){ 183 | return console.error(err); 184 | } 185 | 186 | console.log('successfully updated ' + count + ' person documents'); 187 | 188 | }); 189 | 190 | ``` 191 | The callback will receive any error from mongodb and the count of documents that were updated. 192 | 193 | The output should look something similar to: 194 | 195 | ``` 196 | sucessfully updated 1 person documents 197 | ``` 198 | ## Reading a stored document 199 | 200 | Now that we've successfully inserted and updated a document, let's try retrieving that document. This is very similar to the **find** exercises from module 2 inside the interactive shell. We can query using the node.js driver's **findOne** function to find the document we just inserted. 201 | 202 | FindOne is a convenience function to return the first document from a query - this is useful for queries where you only expect a single document. Let's query by the unique _id field: 203 | 204 | ```js 205 | //retrieve the inserted collection from mongodb 206 | //should be the exact same object we just updated 207 | 208 | bankData.findOne({_id: new ObjectID(result[0]._id)}, function(err,doc){ 209 | 210 | if(err){ 211 | return console.error(err); 212 | } 213 | 214 | console.log('retrieved Person ' + doc.first_name + ' ' + doc.last_name); 215 | console.log('accounts: '); 216 | for(var i in doc.accounts){ 217 | console.log('Type: ' + doc.accounts[i].account_type); 218 | console.log('Balance: ' + doc.accounts[i].account_balance); 219 | } 220 | 221 | return db.close(); 222 | }); 223 | ``` 224 | 225 | The fetched single document is returned to the callback and we can pull out any appropriate fields just as a native javascript object. The output of above should be: 226 | 227 | ``` 228 | retrieved Person Steven Edouard 229 | accounts: 230 | Type: Investment 231 | Balance: 50000000100000 232 | ``` 233 | 234 | ### Deleting a Stored Document 235 | 236 | Finally, to finish our walkthrough on CRUD operations from Node.js, let's delete the record we've inserted. We can do this by calling the **remove** function on the collection object. 237 | 238 | The drop function takes the same type of query projection object as the **find** and **update** functions. 239 | 240 | We'll use the unique **_id** field to delete the exact record we just inserted and updated: 241 | 242 | ```js 243 | //now delete the document we just inserted 244 | 245 | bankData.remove({_id: new ObjectID(result[0]._id)}, function(err,count){ 246 | if(err){ 247 | db.close(); 248 | return console.error(err); 249 | } 250 | 251 | console.log('sucessfully deleted ' + count + ' documents'); 252 | 253 | return db.close(); 254 | }); 255 | ``` 256 | 257 | The output of this should just be: 258 | 259 | ``` 260 | sucessfully deleted 1 documents 261 | ``` 262 | 263 | ## Putting it all together 264 | 265 | In the above snippets we've gone through each type of CRUD operation. We've created a new person document, updated that document, read it and then deleted it. 266 | 267 | Putting all these pieces together in order requires us to interleave the calls within each callback. In Node.js development there are libraries that implement [promises]() or futures that help make your code more linear looking. 268 | 269 | ```js 270 | 271 | var bankData = db.collection('bank_data'); 272 | 273 | bankData.insert({ 274 | first_name: "Steven", 275 | last_name: "Edouard", 276 | accounts: [ 277 | { 278 | account_balance: "50000000", 279 | account_type: "Investment", 280 | currency: "USD" 281 | }] 282 | }, function(err, result){ 283 | 284 | if(err){ 285 | return console.error(err); 286 | } 287 | 288 | console.log('inserted: '); 289 | console.log(result); 290 | console.log('inserted ' + result.length + ' docs'); 291 | 292 | var updatedPerson = result[0]; 293 | updatedPerson.accounts[0].account_balance += 100000; 294 | 295 | bankData.update( { _id: new ObjectID(result[0]._id )}, updatedPerson, {w: 1}, function(err, count){ 296 | 297 | if(err){ 298 | return console.error(err); 299 | } 300 | 301 | console.log('sucessfully updated ' + count + ' person documents'); 302 | 303 | //retrieve the inserted collection from mongodb 304 | //should be the exact same object we just updated 305 | 306 | bankData.findOne({_id: new ObjectID(result[0]._id)}, function(err,doc){ 307 | 308 | if(err){ 309 | return console.error(err); 310 | } 311 | 312 | console.log('retrieved Person ' + doc.first_name + ' ' + doc.last_name); 313 | console.log('accounts: '); 314 | for(var i in doc.accounts){ 315 | console.log('Type: ' + doc.accounts[i].account_type); 316 | console.log('Balance: ' + doc.accounts[i].account_balance); 317 | } 318 | 319 | //now delete the document we just inserted 320 | 321 | bankData.remove({_id: new ObjectID(result[0]._id)}, function(err,count){ 322 | 323 | if(err){ 324 | db.close(); 325 | return console.error(err); 326 | } 327 | 328 | console.log('sucessfully deleted ' + count + ' documents'); 329 | 330 | return db.close(); 331 | }); 332 | 333 | 334 | }); 335 | }); 336 | return; 337 | }); 338 | ``` 339 | 340 | Now we'll go through what the functional equivalent of this code looks like in C#. 341 | 342 | # C# and .NET 343 | 344 | ## Getting Started 345 | 346 | To install the MongoDB driver for C#, you have two options: using [NuGet](http://www.nuget.org/packages/mongocsharpdriver/) or the [MSI installer](https://github.com/mongodb/mongo-csharp-driver/releases). You can also use the sample project in [CSharpStart](./CSharpStart) that includes the NuGet package references. 347 | 348 | 1. To use the NuGet option, you can right-click on your project file in Visual Studio and press the "Manage NuGet Packages..." item. 349 | 350 | ![](ScreenShots/mongo-csharp1.png) 351 | 352 | In the Manage NuGet Packages, you can search for "mongocsharpdriver" in the Online packages and press the Install button on the "Official MongoDB C# driver" search result. 353 | 354 | ![](ScreenShots/mongo-csharp2.png) 355 | 356 | Alternative, you can also execute the following command to install the NuGet package to your project. 357 | 358 | ```batch 359 | Install-Package mongocsharpdriver -Version 1.9.2 360 | ``` 361 | 362 | 2. To use the MSI installer option, download the [CSharpDriver-1.9.2.msi](https://github.com/mongodb/mongo-csharp-driver/releases/download/v1.9.2/CSharpDriver-1.9.2.msi) installer and follow the instructions. After installation is complete, right-click on your project file in Visual Studio and press "Add Reference..." 363 | 364 | ![](ScreenShots/mongo-csharp2.png) 365 | 366 | In the Reference Manager window, go to the "Browse" tab on the left and press the "Browse..." button on the bottom-right. 367 | 368 | ![](ScreenShots/mongo-csharp3.png) 369 | 370 | In the file picker window, navigate to "C:\Program Files (x86)\MongoDB\CSharpDriver 1.9.2\" folder (or wherever you installed the SDK to) and select both DLL files in that folder. Press the "Add" button. 371 | 372 | ![](ScreenShots/mongo-csharp4.png) 373 | 374 | Make sure both MongoDB DLLs are still checked in the Reference Manager and press the "OK" button. 375 | 376 | ![](ScreenShots/mongo-csharp5.png) 377 | 378 | ## Connecting to MongoDB 379 | 380 | Firstly, let's go into our Program.cs file and add the following references to the top of the file. 381 | 382 | ```cs 383 | using MongoDB.Bson; 384 | using MongoDB.Driver; 385 | ``` 386 | 387 | Secondly, let's create a MongoClient and give it a connection URL. MongoClient is thread safe and serves as the root object for working with a MongoDB instance. The connections are handled by the client and are kept in a thread pool, you do not need to call connect or even disconnect. 388 | 389 | ```cs 390 | MongoClient client = new MongoClient("mongodb://127.0.0.1:27017/test"); // connect to localhost 391 | ``` 392 | 393 | Thirdly, you have to get an instance of a MongoServer which gives you advanced ways to get a database and guarantee consistence for your operations. 394 | 395 | ```cs 396 | MongoServer server = client.GetServer(); 397 | MongoDatabase database = server.GetDatabase("test"); // "test" is the name of the database 398 | ``` 399 | 400 | That's all you need to do to connect to MongoDB using the C# driver. 401 | 402 | ## Inserting a new Document 403 | 404 | Now that we can connect to the server lets try inserting a new document into the Person collection. To begin interacting with our Person collection, we'll need to first decide how we want our documents to be represented in our code. 405 | 406 | We have two options to do that; we can use the BsonDocument object or our own data model class. If have not decided how to structure your data and want to take full advantage of Mongo's flexibility, use the BsonDocument object. If you would like a more structured approach to your data or enforce a validation to your documents, you can create your own data model classes. 407 | 408 | ```cs 409 | MongoCollection bankData = database.GetCollection("bank_data"); 410 | ``` 411 | 412 | We can start inserting into this collection reference by simply specifying the object to be inserted into the collection using the BsonDocument object. You'll also notice that we represent arrays with the BsonArray object. 413 | 414 | ```cs 415 | BsonDocument person = new BsonDocument { 416 | { "first_name", "Steven"}, 417 | { "last_name", "Edouard"}, 418 | { "accounts", new BsonArray { 419 | new BsonDocument { 420 | { "account_balance", 50000000}, 421 | { "account_type", "Investment"}, 422 | { "currency", "USD"} 423 | } 424 | }} 425 | }; 426 | bankData.Insert(person); 427 | ``` 428 | 429 | To check if the insert took place correctly, we only need to check that the id of the person has been changed. Notice that we can access any element in our document by using the [] index operator. 430 | 431 | ```cs 432 | System.Console.WriteLine(person["_id"]); 433 | ``` 434 | 435 | Putting everything together to insert the document to our collection: 436 | 437 | ```cs 438 | using MongoDB.Bson; 439 | using MongoDB.Driver; 440 | using System; 441 | using System.Collections.Generic; 442 | using System.Linq; 443 | using System.Text; 444 | using System.Threading.Tasks; 445 | 446 | namespace MongoSample 447 | { 448 | class Program 449 | { 450 | static void Main(string[] args) 451 | { 452 | MongoClient client = new MongoClient("mongodb://127.0.0.1:27017/test"); // connect to localhost 453 | MongoServer server = client.GetServer(); 454 | 455 | MongoDatabase database = server.GetDatabase("test"); // "test" is the name of the database 456 | MongoCollection bankData = database.GetCollection("bank_data"); 457 | BsonDocument person = new BsonDocument { 458 | { "first_name", "Steven"}, 459 | { "last_name", "Edouard"}, 460 | { "accounts", new BsonArray { 461 | new BsonDocument { 462 | { "account_balance", 50000000}, 463 | { "account_type", "Investment"}, 464 | { "currency", "USD"} 465 | } 466 | }} 467 | }; 468 | bankData.Insert(person); 469 | } 470 | } 471 | } 472 | 473 | ``` 474 | 475 | ## Updating a stored document 476 | 477 | We've successfully uploaded a person document, now let's modify the existing document that we've inserted. The above code returns the inserted document upon insert so all we need to to is use the update function to update the document in the database. 478 | 479 | ```cs 480 | //increment this persons balance by 100000 481 | person["accounts"][0]["account_balance"] = person["accounts"][0]["account_balance"].AsInt32 + 100000; 482 | bankData.Save(person); 483 | System.Console.WriteLine("Successfully updated 1 document."); 484 | ``` 485 | 486 | The callback will receive any error from mongodb and the count of documents that were updated. 487 | 488 | The output should look something similar to: 489 | 490 | ``` 491 | Successfully updated 1 document. 492 | ``` 493 | 494 | ## Reading a stored document 495 | 496 | Now that we've successfully inserted and updated a document, let's try retrieving that document. This is very similar to the find exercises from module 2 inside the interactive shell. We can query using the C# driver's FindOne method to find the document we just inserted. 497 | 498 | FindOneById is a convenience method to return the first document from a query - this is useful for queries where you only expect a single document. Let's query by the unique _id field: 499 | 500 | ```cs 501 | //retrieve the inserted collection from mongodb 502 | //should be the exact same object we just updated 503 | BsonDocument newPerson = bankData.FindOneById(person["_id"]); 504 | //check if the account balance was updated. 505 | System.Console.WriteLine(newPerson["accounts"][0]["account_balance"].AsInt32); 506 | ``` 507 | 508 | The fetched single document is returned and we can pull out any appropriate fields just as before. The output of above should be: 509 | ``` 510 | 50100000 511 | ``` 512 | 513 | ## Deleting a Stored Document 514 | 515 | Finally, to finish our walk through on CRUD operations from C#, let's delete the record we've inserted. We can do this by calling the Remove method on the collection object. 516 | 517 | However, the Remove method takes a query parameter of type IMongoQuery. With this query class, we can build or define the attributes/values of the document we are hunting. This is the same query that you can use with the Find() methods to find more than one document or with the Update() method to update more than one document. 518 | 519 | You will need add another using statement to be able to use use the Query object. 520 | 521 | ```cs 522 | using MongoDB.Driver.Builders; 523 | ``` 524 | 525 | To remove a method we will use the equality query to select a document with the same _id as the newPerson document. 526 | 527 | ```cs 528 | //now delete the document we just inserted 529 | var query = Query.EQ("_id", newPerson["_id"]); 530 | WriteConcernResult result = bankData.Remove(query); 531 | System.Console.WriteLine("number of documents removed: " + result.DocumentsAffected); 532 | ``` 533 | 534 | The output of this should just be: 535 | ``` 536 | number of documents removed: 1 537 | ``` 538 | 539 | You can build more complex your queries by using the methods in the Query object. This is an example: 540 | ```cs 541 | var query = Query.And( 542 | Query.EQ("first_name", "Steven"), 543 | Query.EQ("last_name", "Edouard") 544 | ); 545 | ``` 546 | 547 | ## Putting it all together 548 | 549 | In the above snippets we've gone through each type of CRUD operation. We've created a new person document, updated that document, read it and then deleted it. 550 | 551 | ```cs 552 | using MongoDB.Bson; 553 | using MongoDB.Driver; 554 | using MongoDB.Driver.Builders; 555 | using System; 556 | using System.Collections.Generic; 557 | using System.Linq; 558 | using System.Text; 559 | using System.Threading.Tasks; 560 | 561 | namespace MongoSample 562 | { 563 | class Program 564 | { 565 | static void Main(string[] args) 566 | { 567 | MongoClient client = new MongoClient("mongodb://127.0.0.1:27017/test"); // connect to localhost 568 | MongoServer server = client.GetServer(); 569 | 570 | MongoDatabase database = server.GetDatabase("test"); // "test" is the name of the database 571 | MongoCollection bankData = database.GetCollection("bank_data"); 572 | BsonDocument person = new BsonDocument { 573 | { "first_name", "Steven"}, 574 | { "last_name", "Edouard"}, 575 | { "accounts", new BsonArray { 576 | new BsonDocument { 577 | { "account_balance", 50000000}, 578 | { "account_type", "Investment"}, 579 | { "currency", "USD"} 580 | } 581 | }} 582 | }; 583 | bankData.Insert(person); 584 | System.Console.WriteLine(person["_id"]); 585 | 586 | //increment this persons balance by 100000 587 | person["accounts"][0]["account_balance"] = person["accounts"][0]["account_balance"].AsInt32 + 100000; 588 | bankData.Save(person); 589 | System.Console.WriteLine("Successfully updated 1 document."); 590 | 591 | //retrieve the inserted collection from mongodb 592 | //should be the exact same object we just updated 593 | BsonDocument newPerson = bankData.FindOneById(person["_id"]); 594 | //check if the account balance was updated. 595 | System.Console.WriteLine(newPerson["accounts"][0]["account_balance"].AsInt32); 596 | 597 | 598 | 599 | //now delete the document we just inserted 600 | var query = Query.EQ("_id", newPerson["_id"]); 601 | WriteConcernResult result = bankData.Remove(query); 602 | System.Console.WriteLine("number of documents removed: " + result.DocumentsAffected); 603 | } 604 | } 605 | } 606 | ``` 607 | -------------------------------------------------------------------------------- /module3_language_drivers/ScreenShots/mongo-csharp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module3_language_drivers/ScreenShots/mongo-csharp1.png -------------------------------------------------------------------------------- /module3_language_drivers/ScreenShots/mongo-csharp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module3_language_drivers/ScreenShots/mongo-csharp2.png -------------------------------------------------------------------------------- /module3_language_drivers/ScreenShots/mongo-csharp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module3_language_drivers/ScreenShots/mongo-csharp3.png -------------------------------------------------------------------------------- /module3_language_drivers/ScreenShots/mongo-csharp4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module3_language_drivers/ScreenShots/mongo-csharp4.png -------------------------------------------------------------------------------- /module3_language_drivers/ScreenShots/mongo-csharp5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module3_language_drivers/ScreenShots/mongo-csharp5.png -------------------------------------------------------------------------------- /module3_language_drivers/ScreenShots/mongo-csharp6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module3_language_drivers/ScreenShots/mongo-csharp6.png -------------------------------------------------------------------------------- /module3_language_drivers/Start/app.js: -------------------------------------------------------------------------------- 1 | // import the language driver 2 | var MongoClient = require('mongodb').MongoClient 3 | , assert = require('assert'); 4 | var ObjectID = require('mongodb').ObjectID; 5 | // Connection URL 6 | var url = 'mongodb://127.0.0.1:27017/test'; 7 | 8 | // Use connect method to connect to the Server 9 | MongoClient.connect(url, function(err, db) { 10 | 11 | //ensure we've connected 12 | assert.equal(null, err); 13 | 14 | 15 | console.log("Connected correctly to server"); 16 | 17 | 18 | //close the database connection 19 | return db.close(); 20 | 21 | }); -------------------------------------------------------------------------------- /module3_language_drivers/Start/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongodb-mva-nodejs", 3 | "version": "1.0.0", 4 | "description": "generates a test json file for use by mongodb", 5 | "main": "app.js", 6 | "dependencies": { 7 | "async": "^0.9.0", 8 | "mongodb": "^1.4.20" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /module4_advanced_data_ops/End/app.js: -------------------------------------------------------------------------------- 1 | var MongoClient = require('mongodb').MongoClient 2 | , assert = require('assert'); 3 | var ObjectID = require('mongodb').ObjectID; 4 | // Connection URL 5 | var url = 'mongodb://127.0.0.1:27017/test'; 6 | // Use connect method to connect to the Server 7 | MongoClient.connect(url, function(err, db) { 8 | 9 | assert.equal(null, err); 10 | console.log("Connected correctly to server"); 11 | var crimes = db.collection('crimes'); 12 | 13 | 14 | //Question: What day did most crimes occur in chicago from September 2001 to present? 15 | crimes.mapReduce(function(){ 16 | 17 | var milis = Date.parse(this.Date); 18 | var date = new Date(milis); 19 | var daysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; 20 | emit(daysOfWeek[date.getDay()], 1); 21 | }, 22 | function(key, values){ 23 | return Array.sum(values); 24 | }, 25 | { 26 | out: "crime_day_frequencies" 27 | }, 28 | function(err, results, stats){ 29 | 30 | if(err){ 31 | return console.error(err); 32 | } 33 | 34 | var outCollection = db.collection('crime_day_frequencies'); 35 | 36 | outCollection.find().toArray(function(err, docs){ 37 | if(err){ 38 | return console.error(err); 39 | } 40 | 41 | console.log('Number of crimes based on each day of the week'); 42 | 43 | for(var i in docs){ 44 | console.log(docs[i]); 45 | } 46 | return; 47 | }); 48 | }); 49 | 50 | 51 | //question what time of day do most crimes occur? 52 | crimes.mapReduce(function(){ 53 | 54 | var milis = Date.parse(this.Date); 55 | var date = new Date(milis); 56 | //break any given day up into 8 segmets of 3 hours 57 | var timesOfDay = ["12:01AM-3AM", "3:01AM - 6:00AM", "6:01AM - 9:00AM", "9:01AM - 12:00PM", "12:01PM - 3:00PM", "3:01PM - 6:00PM", "6:01PM - 9:00PM", "9:01PM - 12:00AM"]; 58 | 59 | var hours = date.getHours(); 60 | //compute which one of the 8 segmetns of the day this falls into 61 | var timeOfDay = Math.ceil(hours /3); 62 | //get the name of the part of day 63 | var timeOfDayName = timesOfDay[timeOfDay]; 64 | //assign the value 1, to increment the number of crimes that happen this time of day 65 | emit(timeOfDayName, 1); 66 | }, 67 | function(key, values){ 68 | return Array.sum(values); 69 | }, 70 | { 71 | out: "crime_time_frequencies" 72 | }, 73 | function(err, results, stats){ 74 | console.log('completed!'); 75 | if(err){ 76 | return console.error(err); 77 | } 78 | 79 | var outCollection = db.collection('crime_time_frequencies'); 80 | 81 | outCollection.find({}).toArray(function(err, docs){ 82 | if(err){ 83 | return console.error(err); 84 | } 85 | 86 | console.log('Number of crimes based on 3 hour time window during day'); 87 | 88 | for(var i in docs){ 89 | console.log(docs[i]); 90 | } 91 | 92 | return; 93 | }); 94 | 95 | return; 96 | 97 | } 98 | ); 99 | 100 | //Question: what is the most common types of crimes commit in chicago since 2001? 101 | crimes.aggregate({ $group : { _id: "$Primary Type" , count:{$sum: 1} }}, {$sort: { count: -1 } }, 102 | function(err, docs){ 103 | 104 | if(err){ 105 | return console.error(err); 106 | } 107 | 108 | console.log('Crime data by type'); 109 | for(var i in docs){ 110 | console.log(docs[i]); 111 | } 112 | }); 113 | 114 | }); -------------------------------------------------------------------------------- /module4_advanced_data_ops/End/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eventful-node", 3 | "description": "super thin eventful client api library", 4 | "version": "1.1.1", 5 | "dependencies": { 6 | "mongodb": "^1.4.19" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /module4_advanced_data_ops/README.md: -------------------------------------------------------------------------------- 1 | # MongoDB Advanced Data Processing 2 | ---------------------- 3 | 4 | # Objectives 5 | 6 | By the end of this module you'll know how: 7 | 8 | - Load large csv data sets into MongoDB 9 | - The basics of Map Reduce and Aggregations 10 | - To process data with Map/Reduce tasks in MongoDB against a large collection 11 | - To process data MongoDB Aggregation Tasks 12 | 13 | # Introduction 14 | 15 | MongoDB provides support for large data processing tasks such as [Map Reduce](http://docs.mongodb.org/manual/core/map-reduce/) and [Aggregation](http://docs.mongodb.org/manual/core/aggregation-pipeline/). Map Reduce is the process of processing your entire database with 2 steps **Map** and **Reduce**. The Map step maps every document in your database to a category or key. Then in the reduce step, every key reduces all of its mapped values by aggregating all the values with some type of algorithm. 16 | 17 | MongoDB aggregation tasks allow similar operations as Map Reduce but works as a pipeline rather than a 2 step process. Aggregations allow you take a collection and transform it N number of times until you get the collection you desire. The advantage to Aggregations vs Map Reduce is that it allows you to only process the parts of your database you need and exclude parts you don't. Map Reduce requires that your *entire* database be processed. 18 | 19 | # The Example Data Set 20 | 21 | The example data set we will be dealing with is City of Chicago crime police report data from 2001 to 'present' which at the time of writing this is November 2014. The data comes in a large .csv file and we have uploaded a zipped version [here](https://mongdbmva.blob.core.windows.net/csv/crimedata.csv.zip). You can also find the original unzipped download link from the City of Chicago [here](https://data.cityofchicago.org/api/views/ijzp-q8t2/rows.csv?accessType=DOWNLOAD). 22 | 23 | After downloading the CSV file, we can import this data to our database using the ```mongoimport``` utility we used previously to import the test bank_data json: 24 | 25 | ``` 26 | mongoimport Crimes_-_2001_to_present.csv --type csv --headerline --collection crimes 27 | ``` 28 | 29 | The ```--type``` parameter specifies its a csv file, ```--headerline``` indicates that the first line of the csv file has the field names and obviously ```--collection``` specifies the collection to insert the new documents into. 30 | 31 | Doing this command may take a while and it should be noted that you should do this on a fairly fast machine or else working with data this large may hang up your machine. 32 | 33 | Here's what your output will look like: 34 | 35 | ``` 36 | connected to: 127.0.0.1 37 | 2014-11-17T21:36:07.025-0800 Progress: 2756872/1330450848 0% 38 | 2014-11-17T21:36:07.026-0800 11700 3900/second 39 | 2014-11-17T21:36:10.004-0800 Progress: 5634999/1330450848 0% 40 | 2014-11-17T21:36:10.004-0800 23900 3983/second 41 | 2014-11-17T21:36:13.013-0800 Progress: 8629859/1330450848 0% 42 | 2014-11-17T21:36:13.013-0800 36600 4066/second 43 | 2014-11-17T21:36:16.003-0800 Progress: 11551450/1330450848 0% 44 | 2014-11-17T21:36:16.003-0800 49000 4083/second 45 | ``` 46 | 47 | Afterwards you should have about 5.6 million documents uploaded, each representing a police report incident. Here's a sample of what your documents will look like: 48 | 49 | ``` 50 | { "_id" : ObjectId("5462725476ecd357dbbc721e"), "ID" : 9844675, "Case Number" : "HX494115", "Date" : "11/03/2014 11:51:00 PM", "Block" : "056XX S MORGAN ST", "IUCR" : 486, "Primary Type" : "BATTERY", "Description" : "DOMESTIC BATTERY SIMPLE", "Location Description" : "ALLEY", "Arrest" : "false", "Domestic" : "true", "Beat" : 712, "District" : 7, "Ward" : 16, "Community Area" : 68, "FBI Code" : "08B", "X Coordinate" : 1170654, "Y Coordinate" : 1867165, "Year" : 2014, "Updated On" : "11/10/2014 12:43:02 PM", "Latitude" : 41.790980835, "Longitude" : -87.649786614, "Location" : "(41.790980835, -87.649786614)" } 51 | { "_id" : ObjectId("5462725476ecd357dbbc721f"), "ID" : 9844669, "Case Number" : "HX494159", "Date" : "11/03/2014 11:50:00 PM", "Block" : "027XX S HOMAN AVE", "IUCR" : 820, "Primary Type" : "THEFT", "Description" : "$500 AND UNDER", "Location Description" : "RESIDENTIAL YARD (FRONT/BACK)", "Arrest" : "false", "Domestic" : "false", "Beat" : 1032, "District" : 10, "Ward" : 22, "Community Area" : 30, "FBI Code" : 6, "X Coordinate" : 1154188, "Y Coordinate" : 1885408, "Year" : 2014, "Updated On" : "11/10/2014 12:43:02 PM", "Latitude" : 41.841385453, "Longitude" : -87.709678617, "Location" : "(41.841385453, -87.709678617)" } 52 | { "_id" : ObjectId("5462725476ecd357dbbc7220"), "ID" : 9846437, "Case Number" : "HX494607", "Date" : "11/03/2014 11:49:00 PM", "Block" : "008XX N MILWAUKEE AVE", "IUCR" : 4386, "Primary Type" : "OTHER OFFENSE", "Description" : "VIOLATION OF CIVIL NO CONTACT ORDER", "Location Description" : "RESIDENCE", "Arrest" : "false", "Domestic" : "true", "Beat" : 1213, "District" : 12, "Ward" : 27, "Community Area" : 24, "FBI Code" : 26, "X Coordinate" : 1168403, "Y Coordinate" : 1905809, "Year" : 2014, "Updated On" : "11/10/2014 12:43:02 PM", "Latitude" : 41.897072334, "Longitude" : -87.656924505, "Location" : "(41.897072334, -87.656924505)" } 53 | { "_id" : ObjectId("5462725476ecd357dbbc7221"), "ID" : 9844605, "Case Number" : "HX494099", "Date" : "11/03/2014 11:47:00 PM", "Block" : "025XX W 51ST ST", "IUCR" : 1310, "Primary Type" : "CRIMINAL DAMAGE", "Description" : "TO PROPERTY", "Location Description" : "RESIDENCE", "Arrest" : "true", "Domestic" : "false", "Beat" : 923, "District" : 9, "Ward" : 14, "Community Area" : 63, "FBI Code" : 14, "X Coordinate" : 1159952, "Y Coordinate" : 1870801, "Year" : 2014, "Updated On" : "11/10/2014 12:43:02 PM", "Latitude" : 41.801185293, "Longitude" : -87.688928625, "Location" : "(41.801185293, -87.688928625)" } 54 | ``` 55 | # Map Reduce Explained 56 | 57 | The best way to explain map reduce is to attempt to answer a question about the massive amount of data we have. Let's try this one out for size: 58 | 59 | **What day of the week has the most crime incidents recorded in Chicago?** 60 | 61 | [Map Reduce](http://en.wikipedia.org/wiki/MapReduce) breaks down this problem into 2 steps, **Map** and **Reduce**. 62 | 63 | ## Mapping 64 | 65 | The question essentially asks us to break down the number of crimes that have occurred from 2001 in Chicago by day. Notice that for each crime document there is a ```Date``` field which indicates the exact date of the incident. We can use this data to **map** the crime document to a specific day of the week. Here's a graphical view of what we will be doing in this step: 66 | 67 | ![](ScreenShots/mongodbss1.png) 68 | 69 | Each of the 5.6 million police reports will be processed by mongo db and we will specify that we want the document to be mapped to either the 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', or 'Sunday' keys depending on the date field of the document. We do this by calling the **mapReduce** function on the collection. **mapReduce** takes two functions as parameters, a **map** function and a Reduce function. 70 | 71 | The MongoDB driver (and interactive shell) allow us to specify a **map** function which defines how MongoDB will map the documents to their respective keys. To emit a map, the **emit** function can be called within the function to let MongoDB know that you have a mapping for this document. 72 | 73 | Here's what this looks like in code using the NodeJS driver (which is very similar to the interactive shell): 74 | 75 | ```js 76 | //Question: What day of the week do most crimes occur in chicago from September 2001 to present? 77 | crimes.mapReduce(function(){ 78 | 79 | var milis = Date.parse(this.Date); 80 | var date = new Date(milis); 81 | //use a javascript array to create key mappings between 0-6 and Sunday - Saturday 82 | var daysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; 83 | //emit the mapping between this document and the Day which it cooresponds to. 84 | emit(daysOfWeek[date.getDay()], 1); 85 | } 86 | ``` 87 | 88 | Notice that we parse the date field using the Javascript Date class and then use that to easily acquire the day of the week. We then call getDay() to retrieve the day which is a number between 0 and 6. We then use a Javascript array to map those values to a day of the week since every javascript object is already a key/value dictionary. 89 | 90 | We can't execute the code snippet above since it's not complete yet without our **reduce** function. 91 | 92 | ## Reducing 93 | 94 | The second step in this process is to reduce the these mappings into a resulting data set which sort of *summarizes* the mappings we've created. The original question at hand would like us to *summarize* which day of the week crimes happened most frequently in Chicago. 95 | 96 | The Map step has already created a large amount of mappings of 5.6 million crime documents to 7 different types of mappings. If we summarized the data by summing the total number of crime documents for each key (the day of the week) we would quickly be able to answer the question at hand. 97 | 98 | Here's a Visual representation of what the Reduce step does: 99 | 100 | ![](ScreenShots/mongodbss3.png) 101 | 102 | The **reduce** function is the second parameter to the **mapReduce** function where we do this summarization. Reduce is called with 2 parameters, **key** and **values**. 103 | 104 | ```js 105 | function(key, values){ 106 | //reduce the set of values to a single sum. 107 | //the count of values for this day (key) is sufficient enough 108 | return Array.sum(values); 109 | }, 110 | ``` 111 | It turns out that the reduce function for this question is quite easy. We just have to return the number of documents that have been mapped to the key (the day of the week). 112 | 113 | The final parameter for **mapReduce** is the output collection for the results. This is the collection where the results for each key will be placed. We can pass a simple javascript object that specifies this as an **out** collection: 114 | 115 | ```js 116 | { 117 | out: "crime_day_frequencies" 118 | }, 119 | ``` 120 | 121 | Its optional, but let's add a callback function which will output the results upon finishing the map/reduce job. Remember Node.js is asynchronous so the mapReduce function won't stop the application for the task to complete: 122 | 123 | ```js 124 | function(err, results, stats){ 125 | console.log('completed!'); 126 | if(err){ 127 | return console.err(err); 128 | } 129 | 130 | var outCollection = db.collection('crime_day_frequencies'); 131 | 132 | outCollection.find().toArray(function(err, docs){ 133 | if(err){ 134 | return console.error(err); 135 | } 136 | 137 | console.log('Number of crimes based on each day of the week'); 138 | 139 | for(var i in docs){ 140 | console.log(docs[i]); 141 | } 142 | 143 | return; 144 | }); 145 | 146 | }); 147 | ``` 148 | Putting the entire MapReduce call together for Node.js looks like: 149 | 150 | ```js 151 | //Question: What day did most crimes occur in chicago from September 2001 to present? 152 | crimes.mapReduce(function(){ 153 | 154 | var milis = Date.parse(this.Date); 155 | var date = new Date(milis); 156 | var daysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; 157 | //emit the mapping between this document and the Day which it cooresponds to. 158 | emit(daysOfWeek[date.getDay()], 1); 159 | }, 160 | function(key, values){ 161 | //the values parameter will be an array of docs, since thats the value we emitted in map 162 | return values.length; 163 | }, 164 | { 165 | out: "crime_day_frequencies" 166 | }, 167 | function(err, results, stats){ 168 | 169 | if(err){ 170 | return console.err(err); 171 | } 172 | 173 | var outCollection = db.collection('crime_time_frequencies'); 174 | 175 | outCollection.find({}).toArray(function(err, docs){ 176 | if(err){ 177 | return console.error(err); 178 | } 179 | 180 | console.log('Number of crimes based on each day of the week'); 181 | 182 | for(var i in docs){ 183 | console.log(docs[i]); 184 | } 185 | 186 | return; 187 | }); 188 | }); 189 | 190 | ``` 191 | 192 | Finally, the output of this map/reduce job gives us the answer we were looking for in the form of a mongodb collection: 193 | 194 | ``` 195 | Number of crimes based on each day of the week 196 | { _id: 'Friday', value: 854604 } 197 | { _id: 'Monday', value: 798881 } 198 | { _id: 'Saturday', value: 807961 } 199 | { _id: 'Sunday', value: 760800 } 200 | { _id: 'Thursday', value: 810790 } 201 | { _id: 'Tuesday', value: 814967 } 202 | { _id: 'Wednesday', value: 820651 } 203 | ``` 204 | 205 | From the results above, barring any actual statistical science, it appears that the most common day that crimes have occurred in Chicago since 2001 to present has been Fridays. This could be a very interesting insight! 206 | 207 | # Data Aggregations 208 | 209 | Another nifty data processing tool that MongoDB offers is [Aggregations](http://docs.mongodb.org/manual/tutorial/aggregation-zip-code-data-set/). Aggregations work on a concept of processing [pipelines](http://docs.mongodb.org/manual/core/aggregation-pipeline/#id1) which consist of a number of stages. At each stage the data in the returned collection of documents is transformed. 210 | 211 | As before, the best way to learn this concept is by asking a question about the data and using Aggregations to answer it. Let's go with the question: 212 | 213 | **What is the most common type of crime committed in Chicago between 2001 and November 2014?** 214 | 215 | Its possible to answer this with Map/Reduce but let's use Aggregates instead. To do aggregates we first start with the original crimes collection of 5.6 million documents, group those documents by the ```Primary Type``` field, keep track of the count for the number of documents in the Primary Type group and then finally sort those groups by the generated count values. 216 | 217 | Visually we are processing the crimes collection through a series of pipeline steps: 218 | 219 | ![](ScreenShots/mongodbss2.png) 220 | 221 | Stage 0 is the initial collection of Crime elements, which has approximately 5.6 million documents. We then use a [**$group**] (http://docs.mongodb.org/manual/reference/operator/aggregation/group/) operator to group all those documents into groups by ```Primary Type``` which essentially is the type of crime that was committed. 222 | 223 | This leaves us with a new collection of documents one for each group, We will add a **count** field to each group to record how many documents are in that group. Finally we do our next pipeline step which is to sort the input collection which is the collection that came out of the $group operator using the **$sort** operator. We will sort descending by the count field on the grouped collection. 224 | 225 | Here's what this looks like in Node.js code: 226 | 227 | ```js 228 | crimes.aggregate({ $group : { _id: "$Primary Type" , count:{$sum: 1} }}, {$sort: { count: -1 } }, 229 | function(err, docs){ 230 | 231 | if(err){ 232 | return console.error(err); 233 | } 234 | 235 | console.log('Crime data by type'); 236 | for(var i in docs){ 237 | console.log(docs[i]); 238 | } 239 | } 240 | ); 241 | ``` 242 | 243 | For the provided dataset, here are the results, which also yields some interesting insights: 244 | 245 | ``` 246 | { _id: 'THEFT', count: 1168715 } 247 | { _id: 'BATTERY', count: 1033129 } 248 | { _id: 'CRIMINAL DAMAGE', count: 654607 } 249 | { _id: 'NARCOTICS', count: 646714 } 250 | { _id: 'OTHER OFFENSE', count: 349060 } 251 | { _id: 'ASSAULT', count: 343095 } 252 | { _id: 'BURGLARY', count: 334888 } 253 | { _id: 'MOTOR VEHICLE THEFT', count: 271217 } 254 | { _id: 'ROBBERY', count: 212066 } 255 | { _id: 'DECEPTIVE PRACTICE', count: 186657 } 256 | { _id: 'CRIMINAL TRESPASS', count: 166819 } 257 | { _id: 'PROSTITUTION', count: 64586 } 258 | { _id: 'WEAPONS VIOLATION', count: 53954 } 259 | { _id: 'PUBLIC PEACE VIOLATION', count: 40761 } 260 | { _id: 'OFFENSE INVOLVING CHILDREN', count: 35031 } 261 | { _id: 'SEX OFFENSE', count: 20696 } 262 | { _id: 'CRIM SEXUAL ASSAULT', count: 20406 } 263 | { _id: 'GAMBLING', count: 13522 } 264 | { _id: 'LIQUOR LAW VIOLATION', count: 13063 } 265 | { _id: 'ARSON', count: 9363 } 266 | { _id: 'HOMICIDE', count: 6869 } 267 | { _id: 'INTERFERENCE WITH PUBLIC OFFICER', count: 6738 } 268 | { _id: 'KIDNAPPING', count: 5936 } 269 | { _id: 'INTERFERE WITH PUBLIC OFFICER', count: 3760 } 270 | { _id: 'INTIMIDATION', count: 3379 } 271 | { _id: 'STALKING', count: 2653 } 272 | { _id: 'OFFENSES INVOLVING CHILDREN', count: 382 } 273 | { _id: 'OBSCENITY', count: 294 } 274 | { _id: 'PUBLIC INDECENCY', count: 114 } 275 | { _id: 'OTHER NARCOTIC VIOLATION', count: 102 } 276 | { _id: 'NON-CRIMINAL', count: 24 } 277 | { _id: 'RITUALISM', count: 23 } 278 | { _id: 'CONCEALED CARRY LICENSE VIOLATION', count: 14 } 279 | { _id: 'NON - CRIMINAL', count: 13 } 280 | { _id: 'NON-CRIMINAL (SUBJECT SPECIFIED)', count: 3 } 281 | { _id: 'DOMESTIC VIOLENCE', count: 1 } 282 | ``` 283 | 284 | From our results, it would appear that Theft and Battery by far have been the most common types of crimes in Chicago for the past 13 years. 285 | 286 | # Aggregates vs Map/Reduce 287 | 288 | Map Reduce and Aggregations are very powerful tool sets to gain insights into your MongoDB database. It makes sense to compare and contrast the difference between the two. 289 | 290 | Map Reduce is fundamentally designed to process ALL of your data. Every single document is looked at at least once in a a Map/Reduce task. Map reduce allows for more complex logic in mapping documents to keys. Similarly you can implement more complex behavior for reduction as well. 291 | 292 | Aggregations came to MongoDB after version 2.0 partially out of a need to avoid having to process the entire database if it wasn't needed. Because aggregations use a pipeline model, you can chain as many aggregation operations as you'd like and each subsequent operation can perform better given that the operation before reduced the number of documents. 293 | 294 | In short, if the aggregation operators suit your needs and you don't need to process your entire database for each aggregation, than aggregates show a better value. If you constantly process the entire database or have more complex Map or Reduce logic Map/Reduce may be a more attractive option. 295 | 296 | # Conclusion 297 | 298 | Whether you use Map Reduce or Aggregates you will notice that these tasks take quite some time. Due to this these operations are not designed to be real-time requests and thus should really be ran in the background of your application. Think - hourly, daily or weekly runs where you aggregate some result and do something interesting with that data. 299 | 300 | With Map/Reduce and Aggregates you can really find fun and interesting insights without having to write very much code at all. 301 | -------------------------------------------------------------------------------- /module4_advanced_data_ops/ScreenShots/mongodbss1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module4_advanced_data_ops/ScreenShots/mongodbss1.png -------------------------------------------------------------------------------- /module4_advanced_data_ops/ScreenShots/mongodbss2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module4_advanced_data_ops/ScreenShots/mongodbss2.png -------------------------------------------------------------------------------- /module4_advanced_data_ops/ScreenShots/mongodbss3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module4_advanced_data_ops/ScreenShots/mongodbss3.png -------------------------------------------------------------------------------- /module4_advanced_data_ops/Start/app.js: -------------------------------------------------------------------------------- 1 | var MongoClient = require('mongodb').MongoClient 2 | , assert = require('assert'); 3 | var ObjectID = require('mongodb').ObjectID; 4 | // Connection URL 5 | var url = 'mongodb://127.0.0.1:27017/test'; 6 | // Use connect method to connect to the Server 7 | MongoClient.connect(url, function(err, db) { 8 | 9 | assert.equal(null, err); 10 | console.log("Connected correctly to server"); 11 | var crimes = db.collection('crimes'); 12 | 13 | 14 | //Question: What day did most crimes occur in chicago from September 2001 to present? 15 | 16 | //question what time of day do most crimes occur? 17 | 18 | 19 | //Question: what is the most common types of crimes commit in chicago since 2001? 20 | 21 | db.close(); 22 | 23 | 24 | }); -------------------------------------------------------------------------------- /module4_advanced_data_ops/Start/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongodb-mva-nodejs", 3 | "version": "1.0.0", 4 | "main": "app.js", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/sedouard/mongodb-mva.git" 8 | }, 9 | "bugs": { 10 | "url": "https://github.com/sedouard/mongodb-mva/issues" 11 | }, 12 | "homepage": "https://github.com/sedouard/mongodb-mva", 13 | "dependencies": { 14 | "mongodb": "^1.4.26" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /module5_running_in_cloud/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/.DS_Store -------------------------------------------------------------------------------- /module5_running_in_cloud/README.md: -------------------------------------------------------------------------------- 1 | # Running MongoDB on a Cloud Ubuntu VM 2 | 3 | # Objective 4 | 5 | By the end of this module, you'll know how to: 6 | 7 | - Create an Ubuntu Virtual Machine in Azure 8 | - Install MongoDB for Ubuntu 9 | - Configure MongoDB and the Virtual Machine to be accessible by MongoDB clients 10 | 11 | # Introduction 12 | 13 | Now that we've learned the fundamentals of MongoDB, we're ready to deploy MongoDB in the cloud. To do this, we'll spin up a Solid State Disk (SSD) Virtual Machine Ubuntu instance which will host our MongoDB process. We'll then use [ssh](http://en.wikipedia.org/wiki/Secure_Shell) to connect to the machine to install the database and load the data up. 14 | 15 | ## Why an SSD Virtual Machine 16 | 17 | Solid State Disks are what modern high end laptops ship with. These disks have a much higher data transfer rate and don't require a mechanical overhead like traditional hard drives. For a database like MongoDB, not all of your database sits in-memory and for queries that require MongoDB to go to the disk, can take an especially long time if you aren't using an SSD on your machine. 18 | 19 | For this reason, it makes the most sense to use an SSD Virtual Machine for a database like MongoDB. You can checkout more information on Azure 'D' series Virtual Machines which use SSDs [here](http://azure.microsoft.com/blog/2014/09/22/new-d-series-virtual-machine-sizes/). 20 | 21 | ## Why Ubuntu 22 | 23 | There are a couple reasons we are using Ubuntu and not a Windows Server instance for this course. Although MongoDB runs on Windows, its also pretty easy to install mongodb Ubuntu linux as well. If you already have spare Windows Virtual Machines or you are restricted to a heterogenous infrastructure of Windows machine it may make more sense to use Windows to host your MongoDB server. 24 | 25 | Ubuntu Linux is one of the easiest distributions of Linux to use. When we spin up the server, you just need to SSH into the machine, install mongodb with **apt-get** and use Ubuntu Server's service command to start the database as a local service. So in short, Ubuntu is actually one of quickest and easiest OS's to get an open source project like MongoDB up and running. In addition, Linux virtual machines have a lower monthly cost which could be more attractive to startups looking to use cloud services. 26 | 27 | # Creating an Ubuntu Virtual Machine 28 | 29 | To create the Virtual Machine, we'll go into the [Azure portal](http://portal.azure.com) and add a new Ubuntu Server virtual machine. 30 | 31 | First, click the '+' button on the bottom left side of the portal 32 | 33 | ![](ScreenShots/ss1.png) 34 | 35 | Then select the current Ubuntu Server LTS version (LTS means 'Long-term Support') 36 | 37 | ![](ScreenShots/ss2.png) 38 | 39 | You'll then presented with the Create VM blade which will require a few inputs. The name of the VM, the user name you'd like to connect with and the SSH public key that you can generate on your local machine with the [ssh-keygen](http://en.wikipedia.org/wiki/Ssh-keygen) command. 40 | 41 | ![](ScreenShots/ss3.png) 42 | 43 | Generate your ssh public key by executing the command 44 | 45 | ```bash 46 | ssh-keygen -f -P 47 | ``` 48 | 49 | After this command 2 files will exist, a private key and a public key. Here's an example: 50 | 51 | ```bash 52 | Users-Computer-4:ssh-keygen-test user$ ssh-keygen -f mongodbserver -P newAzureVM 53 | Generating public/private rsa key pair. 54 | Your identification has been saved in mongodbserver. 55 | Your public key has been saved in mongodbserver.pub. 56 | The key fingerprint is: 57 | 5d:e5:aa:13:c7:24:13:c8:cd:0c:74:83:fd:ef:9a:2b user@Users-Computer-4.local 58 | The key's randomart image is: 59 | +--[ RSA 2048]----+ 60 | | ooO+ . | 61 | | +.=o o | 62 | | o.o . | 63 | | . *.. | 64 | | S o +. | 65 | | + . | 66 | | o . | 67 | | E. .. | 68 | | .+o | 69 | +-----------------+ 70 | Users-Computer-4:ssh-keygen-test user$ ls 71 | mongodbserver mongodbserver.pub 72 | Users-Computer-4:ssh-keygen-test user$ 73 | ``` 74 | 75 | Copy and past the text from the **.pub** file which is your public key to the **SSH Public Key** box on your portal. 76 | 77 | **Note:** Windows users, an easy way to get ssh and ssh-keygen on your local machine is to install [Github for Windows](http://windows.github.com) and using their provided 'Git Shell'. This shell has ssh and ssh-keygen binaries installed. 78 | 79 | Before you click 'create' you should check out your VM options. For a production deployment its recommend you use a 'D' series virtual machine. If you're just experimenting you can save a lot per month by just picking an Extra Small A0 instance which has no SSD and 1/4th of a core. 80 | 81 | Click 'Create' and your Virtual Machine will be ready in a few minutes. 82 | 83 | # Connecting to your server via SSH 84 | 85 | SSH is the standard way to connect to a Linux/Unix virtual machine. If you need the Graphical User Interface (GUI), its possible to start a VNC server and use a VNC client to get a remote GUI for your Ubuntu server. This walkthrough won't cover that however. 86 | 87 | On your local machine connect to your machine by executing the ssh command with your server name, passing your ssh private key for the identity parameter. Your SSH private key is the file generated by ssh-keygen without the extension '.pub'. 88 | 89 | ``` 90 | ssh @.cloudapp.net -i 91 | ``` 92 | 93 | Once you've successfully logged into your new Ubuntu server you'll see output similar to the following: 94 | 95 | ``` 96 | Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-36-generic x86_64) 97 | 98 | * Documentation: https://help.ubuntu.com/ 99 | 100 | System information as of Tue Nov 18 06:53:49 UTC 2014 101 | 102 | System load: 1.36 Processes: 240 103 | Usage of /: 47.8% of 28.80GB Users logged in: 0 104 | Memory usage: 2% IP address for eth0: 10.0.2.4 105 | Swap usage: 0% 106 | 107 | Graph this data and manage this system at: 108 | https://landscape.canonical.com/ 109 | 110 | Get cloud support with Ubuntu Advantage Cloud Guest: 111 | http://www.ubuntu.com/business/services/cloud 112 | 113 | 55 packages can be updated. 114 | 30 updates are security updates. 115 | 116 | 117 | *** System restart required *** 118 | Last login: Tue Nov 18 06:53:51 2014 from 208.66.28.130 119 | ``` 120 | 121 | Ubuntu will tell you a few basic things about your sever upon login. 122 | 123 | # Installing MongoDB for Ubuntu 124 | 125 | To install MongoDB we can use the debian linux package manager [apt-get](http://linux.die.net/man/8/apt-get) which allows us to easily install software packages for Ubuntu. 126 | 127 | Execute the following command to install mongodb and its associated tools to your server: 128 | 129 | ```bash 130 | # installs the mongodb package key to verify authenticity of package 131 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 132 | # creates a mongodb list file 133 | echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list 134 | # update your package listing to be current 135 | sudo apt-get update 136 | # install the latest version of mongodb 137 | sudo apt-get install -y mongodb-org 138 | ``` 139 | 140 | # Running the MongoDB Server 141 | 142 | Before you fire up your database server, configurations have to be made to connect the server to the MongoDB default port 27107 so that your client applications can connect. 143 | 144 | First, on the VM level we must open up an endpoint on the machine so that the mongodb server is accessible. 145 | 146 | On your azure portal, your Virtual Machine should have ended up on your start board. Click on it's tile: 147 | 148 | ![](ScreenShots/ss5.png) 149 | 150 | In the Virtual Machine Blade click the 'Settings' tile and go to the 'Endpoints' dialog: 151 | 152 | ![](ScreenShots/ss6.png) 153 | 154 | The Endpoints dialog allows you to add a port for MongoDB. To enter a new endpoint click the big '+' button and enter a new TCP endpoint with port number 27107 and name it 'mongodb': 155 | 156 | ![](ScreenShots/ss7.png) 157 | 158 | Finally we must edit the ```/etc/mongo.conf``` file to bind MongoDB to the public 27107 port on the machine. Open up the file with ```vim``` and uncomment this line: 159 | 160 | ``` 161 | sedouard@mongodb-mva:~$ vim /etc/mongod.conf 162 | # Listen to local interface only. Comment out to listen on all interfaces. 163 | # bind_ip = 127.0.0.1 164 | ``` 165 | 166 | To start the mongodb service you can use the Ubuntu local service manager by executing: 167 | 168 | ``` 169 | # start the mongodb database server 170 | sudo service mongod start 171 | ``` 172 | 173 | # Connecting to your MongoDB Server 174 | 175 | ## Interactive Shell 176 | To connect to your mongodb server from the mongodb interactive shell just execute the `mongo` command with the server name, port number and database name as a parameter: 177 | 178 | ``` 179 | mongo mongodb-sedouard.cloudapp.net:27107/test 180 | ``` 181 | 182 | ## Language Driver 183 | 184 | Connecting from a language driver is just as easy. Just use the ```mongodb://``` protocol prefix in your connection string. 185 | 186 | ``` 187 | mongodb://mongodb-sedouard.cloudapp.net:27107/test 188 | ``` 189 | For example, from Node.js this would be: 190 | 191 | ```js 192 | // Connection URL 193 | var url = 'mongodb://mongodb-mva-3dc0g242.cloudapp.net:27017/test'; 194 | // Use connect method to connect to the Server 195 | MongoClient.connect(url, function(err, db) { 196 | 197 | //additional code hidden 198 | ``` 199 | 200 | # Conclusion 201 | 202 | Running MongoDB from Virtual Machine is actually pretty easy to do. Just spin up an Ubuntu Virtual Machine, run a couple commands to get MongoDB up and running and just connect to it like its was your local database. 203 | 204 | Although its relatively easy to to spin up mongodb servers, you should also be aware of our Partner offerings on the Azure store which runs MongoDB as a service. Those service providers are [MongoDB Inc](http://mongodb.org) and [Mongolabs](http://mongolabs.com). The latter has a free service tier for you to get started with MongoDB without having to deal with the details of updating and scaling MongoDB. 205 | 206 | One thing to be aware of however is that if you are using an MSDN subscription from a [Bizspark](http://bizspark.com) or [Bizspark+](http://bizspark.com) member ship, you can't use your Azure credits to pay for these 3rd party services. -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss1.png -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss2.png -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss3.png -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss4.png -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss5.png -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss6.png -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss7.png -------------------------------------------------------------------------------- /module5_running_in_cloud/ScreenShots/ss8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sedouard/mongodb-mva/fbaeb8d848f44d13df3d294df351a88d33e8e94d/module5_running_in_cloud/ScreenShots/ss8.png --------------------------------------------------------------------------------