Mongoskin - Guilin

Post on 10-May-2015

4,638 views 2 download

Tags:

description

NodeParty-SH-1

transcript

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: 'bob@bob.me', 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

guileen@gmail.com