Skip to content

Commit 9da63cc

Browse files
committed
Addressing comments in issue #10
1 parent a3c6c60 commit 9da63cc

1 file changed

Lines changed: 72 additions & 53 deletions

File tree

labs/data_storage.md

Lines changed: 72 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
- How to store data to mongo.
1313
- How to retrieve data from mongo.
1414
- How to run other actions.
15-
* Map Reduce
15+
* Map Reduce
1616

1717
## Lab
1818

@@ -31,11 +31,18 @@
3131
}
3232
}
3333
```
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.
3535

3636
5. Create a file named `index.js`
3737

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+
3946

4047
```javascript
4148
"use strict"
@@ -44,18 +51,21 @@
4451

4552
Next we'll get our mongo Classes
4653

47-
```
54+
```javascript
4855
"use strict"
4956
var CONFIG = require("./config.json").connection,
5057
mongodb = require('mongodb'),
5158
Db = mongodb.Db,
52-
Connection = mongodb.Connection,
5359
Server = mongodb.Server;
5460
```
5561

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`
5764

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).
5969

6070

6171
```javascript
@@ -66,46 +76,48 @@
6676
console.error('Mongo error!', er);
6777
});
6878

69-
mongoDomain.run(function () {
70-
var db = new Db(CONFIG.dbName, new Server(CONFIG.host, CONFIG.port, {safe:true}));
71-
});
7279
```
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.
7382

74-
7. Now lets create our connetion to `mongo`
83+
7. Now lets create our connection to `mongo`
7584

7685
```javascript
7786
mongoDomain.run(function () {
7887
var db = new Db(CONFIG.dbName, new Server(CONFIG.host, CONFIG.port, {safe:true}));
7988
});
8089

81-
8290
```
8391

92+
**Note** At this point we are not connnected to the server.
8493

85-
8. Lets insert some data into mongo.
94+
95+
8. Lets insert some data into `mongo`.
8696

8797
We are going to be inserting a list of users into this database. The data can be found [here](../examples/mongo/assets/users.json)
8898

8999

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.
91101

92102
```javascript
93103
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));
95106
}
96-
```
107+
```
97108

98109
Next lets use `getCollection` in our `insert` function.
99110

100111
```javascript
101112
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+
});
109121
}
110122
```
111123

@@ -115,20 +127,21 @@
115127
//be sure to open your connection
116128
db.open(intercept(function () {
117129
//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+
});
122134
}));
123135
```
124136

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.
126138

127139
```javascript
128140
function remove(cb) {
129141
getCollection("users", function (collection) {
142+
//use intercept to allow us to catch errors
130143
collection.remove(intercept(cb));
131-
});
144+
});
132145
}
133146
```
134147

@@ -137,19 +150,19 @@
137150

138151
```javascript
139152
function reset(cb) {
140-
remove(function () {
141-
insert(cb);
142-
});
153+
remove(function () {
154+
insert(cb);
155+
});
143156
}
144157
```
145158

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`.
147160

148161
```javascript
149162
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+
});
153166
}
154167
```
155168

@@ -203,29 +216,35 @@
203216
});
204217
```
205218

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).
207220

208221
```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+
};
225238
}());
226239

227240
```
228241

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+
229248
Now lets use it and see what we get!
230249

231250
```javascript

0 commit comments

Comments
 (0)