mongoskin - guilin
DESCRIPTION
NodeParty-SH-1TRANSCRIPT
by 桂林
All languages usedAll languages usedAll languages usedAll languages used
Browser script: javaScriptjavaScriptjavaScriptjavaScript
Server script: javaScriptjavaScriptjavaScriptjavaScript
Database script: javaScriptjavaScriptjavaScriptjavaScript
All languages usedAll languages usedAll languages usedAll languages used
Browser script: javaScriptjavaScriptjavaScriptjavaScript
Server script: javaScriptjavaScriptjavaScriptjavaScript
Database script: javaScriptjavaScriptjavaScriptjavaScript
Overview of MongoDB
Patterns of mongoskin
Why MongoDB Why MongoDB Why MongoDB Why MongoDB
AgileAgileAgileAgile and ScalableScalableScalableScalable
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBMySQLMySQLMySQLMySQL
postsid
commentsid
post_id
tagsid
name
posts_tagspost_id
tag_id
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDB
Database >> Database
Table >> Collection
Row >> Document
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBMongoDBMongoDBMongoDBMongoDB{ _id: ObjectId(), title: 'node and mongodb', slug: 'node-and-mongodb', body: '...', published: true, created: new Date('09/01/2011'), updated: new Date('09/16/2011'), comments: [ { author: 'bob', email: '[email protected]', body: '...', created: new Date('09/17/2011') } ], tags: ['MongoDB', 'database']}
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBGet collect ionGet collect ionGet collect ionGet collect ionMongoDB shellposts = db.posts
NodeJSvar mongodb = require('mongodb');var db = new Db('test', new Server(host, port, {}), {native_parser:true});db.open(function(err, db){ db.collection('posts', function(err, posts){ // use posts collection here });});
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBInsertInsertInsertInsertMongoDB shellvar doc = {title: 'test posts', ...};posts.insert(doc);
NodeJSposts.insert(doc, function(err, reply){ // error or done});
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBQueryQueryQueryQueryMongoDB shellposts.find({"comments.author", "bob"})
NodeJSposts.find({"comments.author", "bob"}, function(err, cursor){ cursor.toArray(function(err, docs){ // found docs here });});
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBQuery operatorQuery operatorQuery operatorQuery operator{<field>:{<operator>:<value>}}
db.things.find({j:{$in: [2,4,6]}});
$gt, $lt, $gte, $lte
$all, $exists
$mod, $ne
$in, $nin
$nor, $or, $and
$size, $type, …
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBUpdateUpdateUpdateUpdateMongoDB shellposts.update({_id: doc.id}, {$inc: {votes: 1}})
NodeJSposts.update({_id: doc.id}, {$inc: {votes: 1}}, function(err, count){});
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBModif ier operat ionsModif ier operat ionsModif ier operat ionsModif ier operat ions
$set – set a particular value
$unset – delete a particular field (v1.3+)
$inc – increment a particular value by a certain amount
$push – append a value to an array
$pushAll – append several values to an array
$pull – remove a value(s) from an existing array
$pullAll – remove several value(s) from an existing array
$bit – bitwise operations
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBRemoveRemoveRemoveRemoveMongoDB shellposts.remove({author: 'bob'})
NodeJSposts.remove({author: 'bob'}, function(err, reply){})
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBIndexIndexIndexIndexMongoDB shellposts.ensureIndex({author:1})posts.ensureIndex({slug: 1 }, {unique: true});db.things.ensureIndex( {firstname: 1, lastname: 1}, {unique: true, background:true});
NodeJSposts.ensureIndex({author:1}, function(err, reply){})posts.ensureIndex({slug: 1 }, {unique: true}, function(err, reply){});db.things.ensureIndex( {firstname: 1, lastname: 1}, {unique: true, background:true}, function(err, reply){});
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBGeospatialGeospatialGeospatialGeospatial{ loc : [ 50 , 30 ] } //SUGGESTED OPTION{ loc : { x : 50 , y : 30 } }{ loc : { foo : 50 , y : 30 } }{ loc : { lon : 40.739037, lat: 73.992964 } }
db.places.ensureIndex( { loc : "2d" } )db.places.find( { loc : { $near : [50,50] , $maxDistance : 5 } } )
box = [[40.73083, -73.99756], [40.741404, -73.988135]]db.places.find({"loc" : {"$within" : {"$box" : box}}})
center = [50, 50]radius = 10db.places.find({"loc" : {"$within" : {"$center" : [center, radius]}}})
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBOptimizat ionOptimizat ionOptimizat ionOptimizat ion
Don’t create index for every field
Be careful about single-key indexes with low selectivity.
Only one index could be used per query.
Use compound-key index.db.places.ensureIndex( { location : “2d” , category : 1 } );db.places.find( { location : { $near : [50,50] }, category : ‘coffee’ } );
Use hint. Use explain. Use the profiler.
Pay attention to the read/write ratio of your application.
See docs for more information
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBAggregationAggregationAggregationAggregationposts.count( {author: 'bob'} )posts.distinct("author")
SQL groupselect a,b,sum(c) csum from coll where active=1 group by a,b
MongoDB groupdb.coll.group( {key: { a:true, b:true }, cond: { active:1 }, reduce: function(obj, out) { out.csum += obj.c; }, initial: { csum: 0 } });
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBMapReduceMapReduceMapReduceMapReducemap = function() { for (var i in this.tags) { emit(this.tags[i], 1); }}
reduce = function(key, values) { var count = 0; for (var i in values) { count += current[i]; } return count;}
// 1.8+ must set out collectiondb.posts.mapReduce(map, reduce, {out: 'tags_count'})
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBMapReduceMapReduceMapReduceMapReduce> db.tags_count.find(){"_id" : "MongoDB", "value" : 4}{"_id" : "Map/Reduce", "value" : 2}{"_id" : "Recipe", "value" : 7}{"_id" : "Group", "value" : 1}
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBGridFSGridFSGridFSGridFSUpload imagevar gridStore = new GridStore(db, filename, "w");gridStore.open(function(err, gridStore) { gridStore.write(imageData, function(err, gridStore) { gridStore.close(function(err, result) { console.log(result._id); users.update({_id: userId}, {$set: {avatarId: result._id}}); }); });});
HTML<img src="http://asset.url/gridfs/{{ user.avatarId }}" />
Use nginx-gridfs
Overview of MongoDB Overview of MongoDB Overview of MongoDB Overview of MongoDBReplicat ionReplicat ionReplicat ionReplicat ion and ShardingShardingShardingSharding
NiceNiceNiceNice
NiceNiceNiceNice ,but nodenodenodenode
Nested callbacks, and not DRY?Nested callbacks, and not DRY?Nested callbacks, and not DRY?Nested callbacks, and not DRY?var database = new mongo.Db('testdb', new mongo.Server('localhost', 27017));database.open(function(err, db) { if(err) return handle(err); db.collection('user', function(err, collection) { if(err) return handle(err); collection.find({}, function(err, cursor) { if(err) return handle(err); cursor.toArray(function(err, users) { if(err) return handle(err); doSomething(users); }); }); });});
How to export collect ionHow to export collect ionHow to export collect ionHow to export collect ionvar database = new mongo.Db('testdb', new mongo.Server('localhost', 27017));database.open(function(err, db){ db.collection('posts', function(err, posts) { // can't export here? });});exports.posts = ?
How to share collect ion objectHow to share collect ion objectHow to share collect ion objectHow to share collect ion objectcontrollers/user.jsvar database = new mongo.Db('testdb', new mongo.Server('localhost', 27017));//...database.open(function(err, db){ db.collection('user', function(err, userColl){
userColl.find({}, function(err, cursor){ if(err) return handle(err); cursor.toArray(function(err, users){ res.render('/user.html', {users: users}); }) });
});});
How to share collect ion objectHow to share collect ion objectHow to share collect ion objectHow to share collect ion objectcontrollers/book.jsvar database = new mongo.Db('testdb', new mongo.Server('localhost', 27017));//...database.open(function(err, db){ db.collection('user', function(err, userColl){ userColl.findOne({_id: book.author_id}, function(err, author){ res.render('/book.html', {book: book, author: author}); }); });});
RedsignRedsignRedsignRedsign the API
How about thisHow about thisHow about thisHow about thisconfig.jsexports.db = mongo.db('mongo://localhost:27017/testdb')
And thisAnd thisAnd thisAnd thiscontrollers/user.jsvar db = require('../config').db;db.collection('user').find({}).toArray(function(err, users){ if(err) return handle(err); res.render('/user.html', {users: users});});
And thisAnd thisAnd thisAnd thiscontrollers/book.jsvar db = require('../config').db;db.collection('user').findOne({_id, book.author_id}, function(err, author){ if(err) return handle(err); res.render('/book.html', {book: book, author: author});});
It’s MongoSkinMongoSkinMongoSkinMongoSkin
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinvar mongoskin = require('mongoskin');
var db = mongoskin.db('mongo://localhost:27017/testdb');
db.bind('users');db.bind('books');
db.users.find({}).limit(10).sort({name:-1}).toArray(function(err, users){});
db.books.update({_id: bookId}, {$inc: {votes: 1}}, function(err, reply){});
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinProxy all methodsProxy all methodsProxy all methodsProxy all methodsnode-mongoskinvar skindb = mongoskin.db('mongo://localhost:27017/testdb')function callback(err, reply){}skindb.addUser('foo', 'bar', callback);
node-mongodb-nativevar db = new mongodb.Db('testdb', new mongodb.Server('localhost', 27017));
function callback(err, reply){}db.open(function(err, db){ if(err) return callback(err); db.addUser('foo', 'bar', callback);});
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinSkinClass hold all parameters to open itvar SkinDb = exports.SkinDb = function(db, username, password) { this.db = db; this.username = username; this.password = password; this.state = STATE_CLOSE; this.emitter = new events.EventEmitter(); this._collections = {};};
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinProxy all methods inside openfor (var name in Db.prototype) { SkinDb.prototype[name] = function() { var args = Array.prototype.slice.call(arguments); this.open(function(err, db) { if (err) { return args[args.length - 1](err);//callback(err) } else { return Db.prototype[name].apply(db, args); } }); };}
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinOpen only onceonceonceonce (pseudo-code)SkinDb.prototype.open = function(fn) { switch (this.state) {
case STATE_OPEN: return fn(null, this.db);
case STATE_OPENNING: // if call 'open' method multi times before opened return this.emitter.addListener('open', fn);
case STATE_CLOSE: this.state = STATE_OPENNING; var that = this; this.db.open(function(err, db){ that.db = db; fn(err, db); that.state = STATE_OPEN; that.emitter.emit('open', err, db); }); }
}}; Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin
Returns SkinCollect ionReturns SkinCollect ionReturns SkinCollect ionReturns SkinCollect ionSkinDb.prototype.collection = function(name) { var collection = this._collections[name]; if (!collection) { this._collections[name] = collection = new SkinCollection(this, name); } return collection;};
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinSkinCollect ionSkinCollect ionSkinCollect ionSkinCollect ionvar SkinCollection = exports.SkinCollection = function(skinDb, collectionName) { this.skinDb = skinDb; this.collectionName = collectionName; this.collection; this.state = STATE_CLOSE; this.internalHint; var that = this; this.__defineGetter__('hint', function() { return this.internalHint; }); this.__defineSetter__('hint', function(value) { this.internalHint = value; this.open(function(err, collection) { collection.hint = value; that.internalHint = collection.hint; }); });
this.emitter = new events.EventEmitter();}
}
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinProxy all methods inside SkinCollect ion.openProxy all methods inside SkinCollect ion.openProxy all methods inside SkinCollect ion.openProxy all methods inside SkinCollect ion.openfor (var name in Collection.prototype) { SkinCollection.prototype[name] = function() { var args = Array.prototype.slice.call(arguments); this.open(function(err, collection) { if (err) { args[args.length - 1](err);// callback(err) } else { Collection.prototype[name].apply(collection, args); } }); };}
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinSkinCollect ion.openSkinCollect ion.openSkinCollect ion.openSkinCollect ion.openSkinCollection.prototype.open = function(callback) { //... var that = this; this.skinDb.open(function(err, db){ db.collection(that.collectionName, function(err, collection){ this.nativeCollection = collection; callback(err, collection); } });}
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinReturns SkinCursor if no callbackReturns SkinCursor if no callbackReturns SkinCursor if no callbackReturns SkinCursor if no callbackSkinCollection.prototype.find = function() { var args = Array.prototype.slice.call(arguments); if (args.length > 0 && typeof(args[args.length - 1]) === 'function') { this._find.apply(this, args); }else { return new SkinCursor(null, this, args); }};
And so do with SkinCursorAnd so do with SkinCursorAnd so do with SkinCursorAnd so do with SkinCursor
Patterns of mongoskin Patterns of mongoskin Patterns of mongoskin Patterns of mongoskinPatterns of mongoskinPatterns of mongoskinPatterns of mongoskinPatterns of mongoskin
SkinClass contains all parameters to get NativeObject
Proxy all method inside callback of open()open()open()open()
Make open() method cache result
Return SkinClass object to chain execution
ReferenceReferenceReferenceReference
MongoDB The Definitive Guide
MongoDB Docs http://www.mongodb.org/display/DOCS/Home
MongoDB Cookbook http://cookbook.mongodb.org/
Node mongodb https://github.com/christkv/node-mongodb-native
Mongoskin https://github.com/guileen/node-mongoskin
Thank youThank youThank youThank you桂糊涂@weibo