|
12 | 12 | - How to store data to mongo. |
13 | 13 | - How to retrieve data from mongo. |
14 | 14 | - How to run other actions. |
15 | | - * Map Reduce |
| 15 | + * Map Reduce |
16 | 16 |
|
17 | 17 | ## Lab |
18 | 18 |
|
|
31 | 31 | } |
32 | 32 | } |
33 | 33 | ``` |
34 | | - |
| 34 | + **Note** You could put this in your `index.js` file but it is good practice to keep configuration variables out of your source so you can easily change them later. |
35 | 35 |
|
36 | 36 | 5. Create a file named `index.js` |
37 | 37 |
|
38 | | - At the top of the file require your `config.json` so we can get our connection information. |
| 38 | + First add `"use strict"` to the top of the file to prevent us from doing anything crazy like exporting a global variable! |
| 39 | + |
| 40 | + ```javascript |
| 41 | + "use strict"; |
| 42 | + ``` |
| 43 | + |
| 44 | + Next require your `config.json` so we can get our connection information. |
| 45 | + |
39 | 46 |
|
40 | 47 | ```javascript |
41 | 48 | "use strict" |
|
44 | 51 |
|
45 | 52 | Next we'll get our mongo Classes |
46 | 53 |
|
47 | | - ``` |
| 54 | + ```javascript |
48 | 55 | "use strict" |
49 | 56 | var CONFIG = require("./config.json").connection, |
50 | 57 | mongodb = require('mongodb'), |
51 | 58 | Db = mongodb.Db, |
52 | | - Connection = mongodb.Connection, |
53 | 59 | Server = mongodb.Server; |
54 | 60 | ``` |
55 | 61 |
|
56 | | -6. Create a domain to catch errors from out mongo code. |
| 62 | + * `Server` : This class represents the mongodb server |
| 63 | + * `Db` : This is the class that represents a database on the mongodb `Server` |
57 | 64 |
|
58 | | - The domain will allow us to catch all errors in a single place and know where the errors came from. |
| 65 | +6. Create a domain to catch errors from our mongo code. |
| 66 | + |
| 67 | + |
| 68 | + A domain allows to handle all IO operations as a single group. In this case we want all of our mongo actions to happen in the `mongoDomain` allowing us to catch all errors in a single place. To read more about domains go [here](http://nodejs.org/api/domain.html). |
59 | 69 |
|
60 | 70 |
|
61 | 71 | ```javascript |
|
66 | 76 | console.error('Mongo error!', er); |
67 | 77 | }); |
68 | 78 |
|
69 | | - mongoDomain.run(function () { |
70 | | - var db = new Db(CONFIG.dbName, new Server(CONFIG.host, CONFIG.port, {safe:true})); |
71 | | - }); |
72 | 79 | ``` |
| 80 | + |
| 81 | + Notice how we create a new variable [`intercept`](http://nodejs.org/api/domain.html#domain_domain_intercept_callback) to which is bound to the `mongoDomain` scope. This allows us to reference `intercept` without having to type `mongoDomain.intercept` everytime. |
73 | 82 |
|
74 | | -7. Now lets create our connetion to `mongo` |
| 83 | +7. Now lets create our connection to `mongo` |
75 | 84 |
|
76 | 85 | ```javascript |
77 | 86 | mongoDomain.run(function () { |
78 | 87 | var db = new Db(CONFIG.dbName, new Server(CONFIG.host, CONFIG.port, {safe:true})); |
79 | 88 | }); |
80 | 89 |
|
81 | | - |
82 | 90 | ``` |
83 | 91 |
|
| 92 | + **Note** At this point we are not connnected to the server. |
84 | 93 |
|
85 | | -8. Lets insert some data into mongo. |
| 94 | + |
| 95 | +8. Lets insert some data into `mongo`. |
86 | 96 |
|
87 | 97 | We are going to be inserting a list of users into this database. The data can be found [here](../examples/mongo/assets/users.json) |
88 | 98 |
|
89 | 99 |
|
90 | | - To insert into mongo we need to get a collection, so lets create a function that will automatcially intercept the callback and retrieve the collection. |
| 100 | + To insert into mongo we need to get a collection, so lets create a function that will automatcially intercept the callback and retrieves the collection. |
91 | 101 |
|
92 | 102 | ```javascript |
93 | 103 | function getCollection(collection, cb) { |
94 | | - db.collection(collection, intercept(cb)); |
| 104 | + //use intercept to allow us to catch errors |
| 105 | + db.collection(collection, intercept(cb)); |
95 | 106 | } |
96 | | - ``` |
| 107 | + ``` |
97 | 108 |
|
98 | 109 | Next lets use `getCollection` in our `insert` function. |
99 | 110 |
|
100 | 111 | ```javascript |
101 | 112 | function insert(cb) { |
102 | | - //get our users data |
103 | | - var users = require("./assets/users.json"); |
104 | | - //get the "users collection" |
105 | | - getCollection("users", function (collection) { |
106 | | - //insert the users |
107 | | - collection.insert(users, intercept(cb)); |
108 | | - }); |
| 113 | + //get our users data |
| 114 | + var users = require("./assets/users.json"); |
| 115 | + //get the "users collection" |
| 116 | + getCollection("users", function (collection) { |
| 117 | + //insert the users |
| 118 | + //use intercept to allow us to catch errors |
| 119 | + collection.insert(users, intercept(cb)); |
| 120 | + }); |
109 | 121 | } |
110 | 122 | ``` |
111 | 123 |
|
|
115 | 127 | //be sure to open your connection |
116 | 128 | db.open(intercept(function () { |
117 | 129 | //insert our data |
118 | | - insert(function () { |
119 | | - //we inserted our users! |
120 | | - console.log("Inserted Users!"); |
121 | | - }); |
| 130 | + insert(function () { |
| 131 | + //we inserted our users! |
| 132 | + console.log("Inserted Users!"); |
| 133 | + }); |
122 | 134 | })); |
123 | 135 | ``` |
124 | 136 |
|
125 | | -9. Ok now we can insert we should be able to remove the data. |
| 137 | +9. Ok now that we can insert data we should be able to remove the data too. |
126 | 138 |
|
127 | 139 | ```javascript |
128 | 140 | function remove(cb) { |
129 | 141 | getCollection("users", function (collection) { |
| 142 | + //use intercept to allow us to catch errors |
130 | 143 | collection.remove(intercept(cb)); |
131 | | - }); |
| 144 | + }); |
132 | 145 | } |
133 | 146 | ``` |
134 | 147 |
|
|
137 | 150 |
|
138 | 151 | ```javascript |
139 | 152 | function reset(cb) { |
140 | | - remove(function () { |
141 | | - insert(cb); |
142 | | - }); |
| 153 | + remove(function () { |
| 154 | + insert(cb); |
| 155 | + }); |
143 | 156 | } |
144 | 157 | ``` |
145 | 158 |
|
146 | | -11. Ok lets add a method `count` our data. |
| 159 | +11. Ok lets add a method to `count` the number of users in `mongo`. |
147 | 160 |
|
148 | 161 | ```javascript |
149 | 162 | function getCount(cb) { |
150 | | - getCollection("users", function (collection) { |
151 | | - collection.count(intercept(cb)); |
152 | | - }); |
| 163 | + getCollection("users", function (collection) { |
| 164 | + collection.count(intercept(cb)); |
| 165 | + }); |
153 | 166 | } |
154 | 167 | ``` |
155 | 168 |
|
|
203 | 216 | }); |
204 | 217 | ``` |
205 | 218 |
|
206 | | -13. Now lets add a function to get the count of each users based on the first letter of their first name. To do this we will need to use the [MapReduce](http://www.mongodb.org/display/DOCS/MapReduce). |
| 219 | +13. Next lets add a function that aggregates the users by the first letter in their `firstName` property. To do this we will need to use the [MapReduce](http://www.mongodb.org/display/DOCS/MapReduce). |
207 | 220 |
|
208 | 221 | ```javascript |
209 | | - var getCountByFirstName = (function getCountByFirstName() { |
210 | | - function map() { |
211 | | - if (this.firstName) { |
212 | | - emit(this.firstName.charAt(0), 1); |
213 | | - } |
214 | | - } |
215 | | - |
216 | | - function reduce(key, values) { |
217 | | - return values.length; |
218 | | - } |
219 | | - |
220 | | - return function _getCountByFirstName(cb) { |
221 | | - getCollection("users", function getUsersCollection(collection) { |
222 | | - collection.mapReduce(map, reduce, {out:{inline:1}}, intercept(cb)); |
223 | | - }); |
224 | | - }; |
| 222 | + var getCountByFirstName = (function getCountByFirstName() { |
| 223 | + function map() { |
| 224 | + if (this.firstName) { |
| 225 | + emit(this.firstName.charAt(0), 1); |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + function reduce(key, values) { |
| 230 | + return values.length; |
| 231 | + } |
| 232 | + |
| 233 | + return function _getCountByFirstName(cb) { |
| 234 | + getCollection("users", function getUsersCollection(collection) { |
| 235 | + collection.mapReduce(map, reduce, {out:{inline:1}}, intercept(cb)); |
| 236 | + }); |
| 237 | + }; |
225 | 238 | }()); |
226 | 239 |
|
227 | 240 | ``` |
228 | 241 |
|
| 242 | + What is that function wrapped in parens? That is called an `IIFE` (Immediatly Invoked Function Expression). This allows us to keep `map` and `reduce` private while exposing the `_getCountByFirstName` function. So `getCountByFirstName` is actually assigned to `_getCountByFirstName` while not exposing the private `map` and `reduce` functions. |
| 243 | + |
| 244 | + **Note** the `map` and `reduce` functions are not executed in `node` they are actually serialzed by calling the `toString` and sent to `mongo` to execute on the server. So you **cannot** use any variables that would normally be available (i.e. closure varibles). |
| 245 | + |
| 246 | + Notice how we pass in `{out : {inline : 1}}` this tells mongo to do the map reduce in memory. |
| 247 | + |
229 | 248 | Now lets use it and see what we get! |
230 | 249 |
|
231 | 250 | ```javascript |
|
0 commit comments