|
mongodb是一款文档型的非关系型数据库,性能非常高,老赵做过相关测试,我测试下来也差不多,和sql server相比,写入性能好太多了,下面是我的测试结果:
一条记录4K,1000万的数据占50G磁盘包括索引
Document doc = new Document();
doc.Add("Name", "Joseph" + DateTime.Now.Second); 索引
doc.Add("Age", r.Next(20, 50)); 索引
doc.Add("Time", DateTime.Now);
doc.Add("Data", s);
记录很少的时候写吞吐5000左右
记录很少的时候基于索引的搜索每秒2000左右
数据很少的时候读吞吐每秒1400
数据很少的时候4M数据获取大概237毫秒
数据很少的时候搜索对写入影响不大
数据很少的时候读写相互影响不大
数据很多的时候
写入速度下降一半
读取速度没区别
搜索慢了很多,千万数据200毫秒的搜索速度,2个字段
读取对写入影响还是不大
查询对写入影响很大
另 不管数据量多少CPU始终在10%以下,内存随着数据量增多从20% - 80%
查询:
Document doc = new Document();
doc.Add("Name", "Joseph10");
doc.Add("Age", new Document().Append("$gte", 30).Append("$lte", 40));
读取:
table.FindOne(new Document());
测试程序点击这里下载。测试基于单个master的mongodb,后续测试发现,如果开启master/slave的话,写入速度非常不稳定,在向slave传送数据的时候写入速度下降50%到80%。还有就是mongodb随着并发的上升并没有带来写入速度上的提高,反而下降了一点,可能是因为读写锁的关系。
另外,点击这里下载一个查看mongodb对象的小工具(基于MongoDB.Driver.dll):
列出服务器
列出数据库 表 索引
服务器属性
数据库属性
表属性
列数据
通过写这个工具我觉得,Document使用树形来表示还是很方便的。
我还在想怎么通过类似sql语句的方式查询mongodb,找到了一个gudusoft.gsqlparser,可以解析各种sql,拿来一用,点击这里下载通过sql语句操作mongodb的测试工具,这个工具还是非常原始的版本,只能进行最简单的crud,select不支持group having等子句:
其实把这些小工具组合在一起就是一个简单的mongodb客户管理工具。
在 http://www.mongodb.org/display/DOCS/List+of+Database+Commands 上作者列出了所有db的命令,我们可以通过提交command操作。
在 http://www.mongodb.org/display/DOCS/DBA+Operations+from+the+Shell 上作者列出了可以在mongod工具中做的一些操作,其实这些操作完全可以通过提交command来进行,因为mongod工具完全就是一个javascript写的,我们看一下源代码中的mongo_vstudio.cpp:
const char * jsconcatcode =
"__quiet = false;\n"
"chatty = function(s){\n"
"if ( ! __quiet )\n"
"print( s );}\n"
"friendlyEqual = function( a , b ){\n"
"if ( a == b )\n"
"return true;\n"
"if ( tojson( a ) == tojson( b ) )\n"
"return true;\n"
"return false;}\n"
"doassert = function( msg ){\n"
"print( \"assert: \" + msg );\n"
"throw msg;}\n"
"assert = function( b , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( b )\n"
"return;\n"
"doassert( \"assert failed : \" + msg );}\n"
"assert._debug = false;\n"
"assert.eq = function( a , b , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( a == b )\n"
"return;\n"
"if ( ( a != null && b != null ) && friendlyEqual( a , b ) )\n"
"return;\n"
"doassert( \"[\" + tojson( a ) + \"] != [\" + tojson( b ) + \"] are not equal : \" + msg );}\n"
"assert.neq = function( a , b , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( a != b )\n"
"return;\n"
"doassert( \"[\" + a + \"] != [\" + b + \"] are equal : \" + msg );}\n"
"assert.soon = function( f, msg, timeout, interval ) {\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"var start = new Date();\n"
"timeout = timeout || 30000;\n"
"interval = interval || 200;\n"
"var last;\n"
"while( 1 ) {\n"
"if ( typeof( f ) == \"string\" ){\n"
"if ( eval( f ) )\n"
"return;}\n"
"else {\n"
"if ( f() )\n"
"return;}\n"
"if ( ( new Date() ).getTime() - start.getTime() > timeout )\n"
"doassert( \"assert.soon failed: \" + f + \", msg:\" + msg );\n"
"sleep( interval );}}\n"
"assert.throws = function( func , params , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"try {\n"
"func.apply( null , params );}\n"
"catch ( e ){\n"
"return e;}\n"
"doassert( \"did not throw exception: \" + msg );}\n"
"assert.commandWorked = function( res , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( res.ok == 1 )\n"
"return;\n"
"doassert( \"command failed: \" + tojson( res ) + \" : \" + msg );}\n"
"assert.commandFailed = function( res , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( res.ok == 0 )\n"
"return;\n"
"doassert( \"command worked when it should have failed: \" + tojson( res ) + \" : \" + msg );}\n"
"assert.isnull = function( what , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( what == null )\n"
"return;\n"
"doassert( \"supposed to null (\" + ( msg || \"\" ) + \") was: \" + tojson( what ) );}\n"
"assert.lt = function( a , b , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( a < b )\n"
"return;\n"
"doassert( a + \" is not less than \" + b + \" : \" + msg );}\n"
"assert.gt = function( a , b , msg ){\n"
"if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n"
"if ( a > b )\n"
"return;\n"
"doassert( a + \" is not greater than \" + b + \" : \" + msg );}\n"
"assert.close = function( a , b , msg ){\n"
"var diff = Math.abs( (a-b)/((a+b)/2) );\n"
"if ( diff < .001 )\n"
"return;\n"
"doassert( a + \" is not close to \" + b + \" diff: \" + diff + \" : \" + msg );}\n"
"Object.extend = function( dst , src , deep ){\n"
"for ( var k in src ){\n"
"var v = src[k];\n"
"if ( deep && typeof(v) == \"object\" ){\n"
"v = Object.extend( typeof ( v.length ) == \"number\" ? [] : {} , v , true );}\n"
"dst[k] = v;}\n"
"return dst;}\n"
"argumentsToArray = function( a ){\n"
"var arr = [];\n"
"for ( var i=0; i>>>>>> skipping \" + x.name);\n"
"return;}\n"
"params[ i % n ].push( x.name );\n"
"++i;}\n"
");\n"
"params[ 0 ] = Array.shuffle( params[ 0 ] );\n"
"for( var i in params ) {\n"
"params[ i ].unshift( i );}\n"
"return params;}\n"
"ParallelTester.fileTester = function() {\n"
"var args = argumentsToArray( arguments );\n"
"var suite = args.shift();\n"
"args.forEach(\n"
"function( x ) {\n"
"print(\" S\" + suite + \" Test : \" + x + \" ...\");\n"
"var time = Date.timeFunc( function() { load(x); }, 1);\n"
"print(\" S\" + suite + \" Test : \" + x + \" \" + time + \"ms\" );}\n"
");}\n"
"assert.parallelTests = function( params, msg, newScopes ) {\n"
"newScopes = newScopes || false;\n"
"var wrapper = function( fun, argv ) {\n"
"eval (\n"
"\"var z = function() {\" +\n"
"\"var __parallelTests__fun = \" + fun.toString() + \";\" +\n"
"\"var __parallelTests__argv = \" + tojson( argv ) + \";\" +\n"
"\"var __parallelTests__passed = false;\" +\n"
"\"try {\" +\n"
"\"__parallelTests__fun.apply( 0, __parallelTests__argv );\" +\n"
"\"__parallelTests__passed = true;\" +\n"
"\"} catch ( e ) {\" +\n"
"\"print( e );\" +\n"
"\"}\" +\n"
"\"return __parallelTests__passed;\" +\n"
"\"}\"\n"
");\n"
"return z;}\n"
"var runners = new Array();\n"
"for( var i in params ) {\n"
"var param = params[ i ];\n"
"var test = param.shift();\n"
"var t;\n"
"if ( newScopes )\n"
"t = new ScopedThread( wrapper( test, param ) );\n"
"else\n"
"t = new Thread( wrapper( test, param ) );\n"
"runners.push( t );}\n"
"runners.forEach( function( x ) { x.start(); } );\n"
"var nFailed = 0;\n"
"runners.forEach( function( x ) { if( !x.returnData() ) { ++nFailed; } } );\n"
"assert.eq( 0, nFailed, msg );}}\n"
"tojson = function( x, indent , nolint ){\n"
"if ( x === null )\n"
"return \"null\";\n"
"if ( x === undefined )\n"
"return \"undefined\";\n"
"if (!indent)\n"
"indent = \"\";\n"
"switch ( typeof x ){\n"
"case \"string\": {\n"
"var s = \"\\\"\";\n"
"for ( var i=0; i= 0 , \"unexpected error: \" + tojson( e ) );\n"
"print( \"server should be down...\" );}}\n"
"\n"
"DB.prototype.cloneDatabase = function(from) {\n"
"assert( isString(from) && from.length );\n"
"return this._dbCommand( { clone: from } );}\n"
"\n"
"DB.prototype.cloneCollection = function(from, collection, query) {\n"
"assert( isString(from) && from.length );\n"
"assert( isString(collection) && collection.length );\n"
"collection = this._name + \".\" + collection;\n"
"query = query || {};\n"
"return this._dbCommand( { cloneCollection:collection, from:from, query:query } );}\n"
"\n"
"DB.prototype.copyDatabase = function(fromdb, todb, fromhost, username, password) {\n"
"assert( isString(fromdb) && fromdb.length );\n"
"assert( isString(todb) && todb.length );\n"
"fromhost = fromhost || \"\";\n"
"if ( username && password ) {\n"
"var n = this._adminCommand( { copydbgetnonce : 1, fromhost:fromhost } );\n"
"return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb, username:username, nonce:n.nonce, key:this.__pwHash( n.nonce, username, password ) } );\n"
"} else {\n"
"return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } );}}\n"
"\n"
"DB.prototype.repairDatabase = function() {\n"
"return this._dbCommand( { repairDatabase: 1 } );}\n"
"DB.prototype.help = function() {\n"
"print(\"DB methods:\");\n"
"print(\"\\tdb.addUser(username, password[,])\");\n"
"print(\"\\tdb.auth(username, password)\");\n"
"print(\"\\tdb.cloneDatabase(fromhost)\");\n"
"print(\"\\tdb.commandHelp(name) returns the help for the command\");\n"
"print(\"\\tdb.copyDatabase(fromdb, todb, fromhost)\");\n"
"print(\"\\tdb.createCollection(name, { size : ..., capped : ..., max : ... } )\");\n"
"print(\"\\tdb.currentOp() displays the current operation in the db\" );\n"
"print(\"\\tdb.dropDatabase()\");\n"
"print(\"\\tdb.eval(func, args) run code server-side\");\n"
"print(\"\\tdb.getCollection(cname) same as db['cname'] or db.cname\");\n"
"print(\"\\tdb.getCollectionNames()\");\n"
"print(\"\\tdb.getLastError() - just returns the err msg string\");\n"
"print(\"\\tdb.getLastErrorObj() - return full status object\");\n"
"print(\"\\tdb.getMongo() get the server connection object\");\n"
"print(\"\\tdb.getMongo().setSlaveOk() allow this connection to read from the nonmaster member of a replica pair\");\n"
"print(\"\\tdb.getName()\");\n"
"print(\"\\tdb.getPrevError()\");\n"
"print(\"\\tdb.getProfilingLevel()\");\n"
"print(\"\\tdb.getReplicationInfo()\");\n"
"print(\"\\tdb.getSisterDB(name) get the db at the same server as this onew\");\n"
"print(\"\\tdb.killOp(opid) kills the current operation in the db\" );\n"
"print(\"\\tdb.printCollectionStats()\" );\n"
"print(\"\\tdb.printReplicationInfo()\");\n"
"print(\"\\tdb.printSlaveReplicationInfo()\");\n"
"print(\"\\tdb.printShardingStatus()\");\n"
"print(\"\\tdb.removeUser(username)\");\n"
"print(\"\\tdb.repairDatabase()\");\n"
"print(\"\\tdb.resetError()\");\n"
"print(\"\\tdb.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 }\");\n"
"print(\"\\tdb.setProfilingLevel(level,) 0=off 1=slow 2=all\");\n"
"print(\"\\tdb.shutdownServer()\");\n"
"print(\"\\tdb.stats()\");\n"
"print(\"\\tdb.version() current version of the server\" );}\n"
"DB.prototype.printCollectionStats = function(){\n"
"var mydb = this;\n"
"this.getCollectionNames().forEach(\n"
"function(z){\n"
"print( z );\n"
"printjson( mydb.getCollection(z).stats() );\n"
"print( \"---\" );}\n"
");}\n"
"\n"
"DB.prototype.setProfilingLevel = function(level,slowms) {\n"
"if (level < 0 || level > 2) {\n"
"throw { dbSetProfilingException : \"input level \" + level + \" is out of range [0..2]\" };}\n"
"var cmd = { profile: level };\n"
"if ( slowms )\n"
"cmd[\"slowms\"] = slowms;\n"
"return this._dbCommand( cmd );}\n"
"\n"
"DB.prototype.eval = function(jsfunction) {\n"
"var cmd = { $eval : jsfunction };\n"
"if ( arguments.length > 1 ) {\n"
"cmd.args = argumentsToArray( arguments ).slice(1);}\n"
"var res = this._dbCommand( cmd );\n"
"if (!res.ok)\n"
"throw tojson( res );\n"
"return res.retval;}\n"
"DB.prototype.dbEval = DB.prototype.eval;\n"
"\n"
"DB.prototype.groupeval = function(parmsObj) {\n"
"var groupFunction = function() {\n"
"var parms = args[0];\n"
"var c = db[parms.ns].find(parms.cond||{});\n"
"var map = new Map();\n"
"var pks = parms.key ? Object.keySet( parms.key ) : null;\n"
"var pkl = pks ? pks.length : 0;\n"
"var key = {};\n"
"while( c.hasNext() ) {\n"
"var obj = c.next();\n"
"if ( pks ) {\n"
"for( var i=0; i= 0 && name != \"local.oplog.$main\" )\n"
"return;\n"
"all.push( name.substring( nsLength ) );}\n"
");\n"
"return all;}\n"
"DB.prototype.tojson = function(){\n"
"return this._name;}\n"
"DB.prototype.toString = function(){\n"
"return this._name;}\n"
"DB.prototype.currentOp = function(){\n"
"return db.$cmd.sys.inprog.findOne();}\n"
"DB.prototype.currentOP = DB.prototype.currentOp;\n"
"DB.prototype.killOp = function(op) {\n"
"if( !op )\n"
"throw \"no opNum to kill specified\";\n"
"return db.$cmd.sys.killop.findOne({'op':op});}\n"
"DB.prototype.killOP = DB.prototype.killOp;\n"
"DB.tsToSeconds = function(x){\n"
"if ( x.t && x.i )\n"
"return x.t / 1000;\n"
"return x / 4294967296;}\n"
"\n"
"DB.prototype.getReplicationInfo = function() {\n"
"var db = this.getSisterDB(\"local\");\n"
"var result = { };\n"
"var ol = db.system.namespaces.findOne({name:\"local.oplog.$main\"});\n"
"if( ol && ol.options ) {\n"
"result.logSizeMB = ol.options.size / 1000 / 1000;\n"
"} else {\n"
"result.errmsg = \"local.oplog.$main, or its options, not found in system.namespaces collection (not --master?)\";\n"
"return result;}\n"
"var firstc = db.oplog.$main.find().sort({$natural:1}).limit(1);\n"
"var lastc = db.oplog.$main.find().sort({$natural:-1}).limit(1);\n"
"if( !firstc.hasNext() || !lastc.hasNext() ) {\n"
"result.errmsg = \"objects not found in local.oplog.$main -- is this a new and empty db instance?\";\n"
"result.oplogMainRowCount = db.oplog.$main.count();\n"
"return result;}\n"
"var first = firstc.next();\n"
"var last = lastc.next();\n"
"{\n"
"var tfirst = first.ts;\n"
"var tlast = last.ts;\n"
"if( tfirst && tlast ) {\n"
"tfirst = DB.tsToSeconds( tfirst );\n"
"tlast = DB.tsToSeconds( tlast );\n"
"result.timeDiff = tlast - tfirst;\n"
"result.timeDiffHours = Math.round(result.timeDiff / 36)/100;\n"
"result.tFirst = (new Date(tfirst*1000)).toString();\n"
"result.tLast = (new Date(tlast*1000)).toString();\n"
"result.now = Date();}\n"
"else {\n"
"result.errmsg = \"ts element not found in oplog objects\";}}\n"
"return result;}\n"
"DB.prototype.printReplicationInfo = function() {\n"
"var result = this.getReplicationInfo();\n"
"if( result.errmsg ) {\n"
"print(tojson(result));\n"
"return;}\n"
"print(\"configured oplog size: \" + result.logSizeMB + \"MB\");\n"
"print(\"log length start to end: \" + result.timeDiff + \"secs (\" + result.timeDiffHours + \"hrs)\");\n"
"print(\"oplog first event time: \" + result.tFirst);\n"
"print(\"oplog last event time: \" + result.tLast);\n"
"print(\"now: \" + result.now);}\n"
"DB.prototype.printSlaveReplicationInfo = function() {\n"
"function g(x) {\n"
"print(\"source: \" + x.host);\n"
"var st = new Date( DB.tsToSeconds( x.syncedTo ) * 1000 );\n"
"var now = new Date();\n"
"print(\"syncedTo: \" + st.toString() );\n"
"var ago = (now-st)/1000;\n"
"var hrs = Math.round(ago/36)/100;\n"
"print(\" = \" + Math.round(ago) + \"secs ago (\" + hrs + \"hrs)\");}\n"
"var L = this.getSisterDB(\"local\");\n"
"if( L.sources.count() == 0 ) {\n"
"print(\"local.sources is empty; is this db a --slave?\");\n"
"return;}\n"
"L.sources.find().forEach(g);}\n"
"DB.prototype.serverBuildInfo = function(){\n"
"return this._adminCommand( \"buildinfo\" );}\n"
"DB.prototype.serverStatus = function(){\n"
"return this._adminCommand( \"serverStatus\" );}\n"
"DB.prototype.version = function(){\n"
"return this.serverBuildInfo().version;}\n"
"DB.prototype.printShardingStatus = function(){\n"
"printShardingStatus( this.getSisterDB( \"config\" ) );}\n"
"if ( typeof Mongo == \"undefined\" ){\n"
"Mongo = function( host ){\n"
"this.init( host );}}\n"
"if ( ! Mongo.prototype ){\n"
"throw \"Mongo.prototype not defined\";}\n"
"if ( ! Mongo.prototype.find )\n"
"Mongo.prototype.find = function( ns , query , fields , limit , skip ){ throw \"find not implemented\"; }\n"
"if ( ! Mongo.prototype.insert )\n"
"Mongo.prototype.insert = function( ns , obj ){ throw \"insert not implemented\"; }\n"
"if ( ! Mongo.prototype.remove )\n"
"Mongo.prototype.remove = function( ns , pattern ){ throw \"remove not implemented;\" }\n"
"if ( ! Mongo.prototype.update )\n"
"Mongo.prototype.update = function( ns , query , obj , upsert ){ throw \"update not implemented;\" }\n"
"if ( typeof mongoInject == \"function\" ){\n"
"mongoInject( Mongo.prototype );}\n"
"Mongo.prototype.setSlaveOk = function() {\n"
"this.slaveOk = true;}\n"
"Mongo.prototype.getDB = function( name ){\n"
"return new DB( this , name );}\n"
"Mongo.prototype.getDBs = function(){\n"
"var res = this.getDB( \"admin\" ).runCommand( { \"listDatabases\" : 1 } );\n"
"assert( res.ok == 1 , \"listDatabases failed:\" + tojson( res ) );\n"
"return res;}\n"
"Mongo.prototype.getDBNames = function(){\n"
"return this.getDBs().databases.map(\n"
"function(z){\n"
"return z.name;}\n"
");}\n"
"Mongo.prototype.getCollection = function(ns){\n"
"var idx = ns.indexOf( \".\" );\n"
"if ( idx < 0 )\n"
"throw \"need . in ns\";\n"
"var db = ns.substring( 0 , idx );\n"
"var c = ns.substring( idx + 1 );\n"
"return this.getDB( db ).getCollection( c );}\n"
"Mongo.prototype.toString = function(){\n"
"return \"mongo connection to \" + this.host;}\n"
"connect = function( url , user , pass ){\n"
"chatty( \"connecting to: \" + url )\n"
"if ( user && ! pass )\n"
"throw \"you specified a user and not a password. either you need a password, or you're using the old connect api\";\n"
"var idx = url.indexOf( \"/\" );\n"
"var db;\n"
"if ( idx < 0 )\n"
"db = new Mongo().getDB( url );\n"
"else\n"
"db = new Mongo( url.substring( 0 , idx ) ).getDB( url.substring( idx + 1 ) );\n"
"if ( user && pass ){\n"
"if ( ! db.auth( user , pass ) ){\n"
"throw \"couldn't login\";}}\n"
"return db;}\n"
"MR = {};\n"
"MR.init = function(){\n"
"$max = 0;\n"
"$arr = [];\n"
"emit = MR.emit;\n"
"$numEmits = 0;\n"
"$numReduces = 0;\n"
"$numReducesToDB = 0;\n"
"gc();}\n"
"MR.cleanup = function(){\n"
"MR.init();\n"
"gc();}\n"
"MR.emit = function(k,v){\n"
"$numEmits++;\n"
"var num = nativeHelper.apply( get_num_ , [ k ] );\n"
"var data = $arr[num];\n"
"if ( ! data ){\n"
"data = { key : k , values : new Array(1000) , count : 0 };\n"
"$arr[num] = data;}\n"
"data.values[data.count++] = v;\n"
"$max = Math.max( $max , data.count );}\n"
"MR.doReduce = function( useDB ){\n"
"$numReduces++;\n"
"if ( useDB )\n"
"$numReducesToDB++;\n"
"$max = 0;\n"
"for ( var i=0; i 0 ) {\n"
"ret.unique = true;}\n"
"if ( nTrue > 1 ) {\n"
"ret.dropDups = true;}}\n"
"*/\n"
"return ret;}\n"
"DBCollection.prototype.createIndex = function( keys , options ){\n"
"var o = this._indexSpec( keys, options );\n"
"this._db.getCollection( \"system.indexes\" ).insert( o , true );}\n"
"DBCollection.prototype.ensureIndex = function( keys , options ){\n"
"var name = this._indexSpec( keys, options ).name;\n"
"this._indexCache = this._indexCache || {};\n"
"if ( this._indexCache[ name ] ){\n"
"return;}\n"
"this.createIndex( keys , options );\n"
"if ( this.getDB().getLastError() == \"\" ) {\n"
"this._indexCache[name] = true;}}\n"
"DBCollection.prototype.resetIndexCache = function(){\n"
"this._indexCache = {};}\n"
"DBCollection.prototype.reIndex = function() {\n"
"return this._db.runCommand({ reIndex: this.getName() });}\n"
"DBCollection.prototype.dropIndexes = function(){\n"
"this.resetIndexCache();\n"
"var res = this._db.runCommand( { deleteIndexes: this.getName(), index: \"*\" } );\n"
"assert( res , \"no result from dropIndex result\" );\n"
"if ( res.ok )\n"
"return res;\n"
"if ( res.errmsg.match( /not found/ ) )\n"
"return res;\n"
"throw \"error dropping indexes : \" + tojson( res );}\n"
"DBCollection.prototype.drop = function(){\n"
"this.resetIndexCache();\n"
"var ret = this._db.runCommand( { drop: this.getName() } );\n"
"if ( ! ret.ok ){\n"
"if ( ret.errmsg == \"ns not found\" )\n"
"return false;\n"
"throw \"drop failed: \" + tojson( ret );}\n"
"return true;}\n"
"DBCollection.prototype.findAndModify = function(args){\n"
"var cmd = { findandmodify: this.getName() };\n"
"for (var key in args){\n"
"cmd[key] = args[key];}\n"
"var ret = this._db.runCommand( cmd );\n"
"if ( ! ret.ok ){\n"
"if (ret.errmsg == \"No matching object found\"){\n"
"return {};}\n"
"throw \"findAndModifyFailed failed: \" + tojson( ret.errmsg );}\n"
"return ret.value;}\n"
"DBCollection.prototype.renameCollection = function( newName , dropTarget ){\n"
"return this._db._adminCommand( { renameCollection : this._fullName ,\n"
"to : this._db._name + \".\" + newName ,\n"
"dropTarget : dropTarget } )}\n"
"DBCollection.prototype.validate = function() {\n"
"var res = this._db.runCommand( { validate: this.getName() } );\n"
"res.valid = false;\n"
"if ( res.result ){\n"
"var str = \"-\" + tojson( res.result );\n"
"res.valid = ! ( str.match( /exception/ ) || str.match( /corrupt/ ) );\n"
"var p = /lastExtentSize:(\\d+)/;\n"
"var r = p.exec( str );\n"
"if ( r ){\n"
"res.lastExtentSize = Number( r[1] );}}\n"
"return res;}\n"
"DBCollection.prototype.getShardVersion = function(){\n"
"return this._db._adminCommand( { getShardVersion : this._fullName } );}\n"
"DBCollection.prototype.getIndexes = function(){\n"
"return this.getDB().getCollection( \"system.indexes\" ).find( { ns : this.getFullName() } ).toArray();}\n"
"DBCollection.prototype.getIndices = DBCollection.prototype.getIndexes;\n"
"DBCollection.prototype.getIndexSpecs = DBCollection.prototype.getIndexes;\n"
"DBCollection.prototype.getIndexKeys = function(){\n"
"return this.getIndexes().map(\n"
"function(i){\n"
"return i.key;}\n"
");}\n"
"DBCollection.prototype.count = function( x ){\n"
"return this.find( x ).count();}\n"
"\n"
"DBCollection.prototype.clean = function() {\n"
"return this._dbCommand( { clean: this.getName() } );}\n"
"\n"
"DBCollection.prototype.dropIndex = function(index) {\n"
"assert(index , \"need to specify index to dropIndex\" );\n"
"if ( ! isString( index ) && isObject( index ) )\n"
"index = this._genIndexName( index );\n"
"var res = this._dbCommand( \"deleteIndexes\" ,{ index: index } );\n"
"this.resetIndexCache();\n"
"return res;}\n"
"DBCollection.prototype.copyTo = function( newName ){\n"
"return this.getDB().eval(\n"
"function( collName , newName ){\n"
"var from = db[collName];\n"
"var to = db[newName];\n"
"to.ensureIndex( { _id : 1 } );\n"
"var count = 0;\n"
"var cursor = from.find();\n"
"while ( cursor.hasNext() ){\n"
"var o = cursor.next();\n"
"count++;\n"
"to.save( o );}\n"
"return count;\n"
"} , this.getName() , newName\n"
");}\n"
"DBCollection.prototype.getCollection = function( subName ){\n"
"return this._db.getCollection( this._shortName + \".\" + subName );}\n"
"DBCollection.prototype.stats = function( scale ){\n"
"return this._db.runCommand( { collstats : this._shortName , scale : scale } );}\n"
"DBCollection.prototype.dataSize = function(){\n"
"return this.stats().size;}\n"
"DBCollection.prototype.storageSize = function(){\n"
"return this.stats().storageSize;}\n"
"DBCollection.prototype.totalIndexSize = function( verbose ){\n"
"var stats = this.stats();\n"
"if (verbose){\n"
"for (var ns in stats.indexSizes){\n"
"print( ns + \"\\t\" + stats.indexSizes[ns] );}}\n"
"return stats.totalIndexSize;}\n"
"DBCollection.prototype.totalSize = function(){\n"
"var total = this.storageSize();\n"
"var mydb = this._db;\n"
"var shortName = this._shortName;\n"
"this.getIndexes().forEach(\n"
"function( spec ){\n"
"var coll = mydb.getCollection( shortName + \".$\" + spec.name );\n"
"var mysize = coll.storageSize();\n"
"total += coll.dataSize();}\n"
");\n"
"return total;}\n"
"DBCollection.prototype.convertToCapped = function( bytes ){\n"
"if ( ! bytes )\n"
"throw \"have to specify # of bytes\";\n"
"return this._dbCommand( { convertToCapped : this._shortName , size : bytes } )}\n"
"DBCollection.prototype.exists = function(){\n"
"return this._db.system.namespaces.findOne( { name : this._fullName } );}\n"
"DBCollection.prototype.isCapped = function(){\n"
"var e = this.exists();\n"
"return ( e && e.options && e.options.capped ) ? true : false;}\n"
"DBCollection.prototype.distinct = function( keyString , query ){\n"
"var res = this._dbCommand( { distinct : this._shortName , key : keyString , query : query || {} } );\n"
"if ( ! res.ok )\n"
"throw \"distinct failed: \" + tojson( res );\n"
"return res.values;}\n"
"DBCollection.prototype.group = function( params ){\n"
"params.ns = this._shortName;\n"
"return this._db.group( params );}\n"
"DBCollection.prototype.groupcmd = function( params ){\n"
"params.ns = this._shortName;\n"
"return this._db.groupcmd( params );}\n"
"MapReduceResult = function( db , o ){\n"
"Object.extend( this , o );\n"
"this._o = o;\n"
"this._keys = Object.keySet( o );\n"
"this._db = db;\n"
"this._coll = this._db.getCollection( this.result );}\n"
"MapReduceResult.prototype._simpleKeys = function(){\n"
"return this._o;}\n"
"MapReduceResult.prototype.find = function(){\n"
"return DBCollection.prototype.find.apply( this._coll , arguments );}\n"
"MapReduceResult.prototype.drop = function(){\n"
"return this._coll.drop();}\n"
"\n"
"MapReduceResult.prototype.convertToSingleObject = function(){\n"
"var z = {};\n"
"this._coll.find().forEach( function(a){ z[a._id] = a.value; } );\n"
"return z;}\n"
"\n"
"DBCollection.prototype.mapReduce = function( map , reduce , optional ){\n"
"var c = { mapreduce : this._shortName , map : map , reduce : reduce };\n"
"if ( optional )\n"
"Object.extend( c , optional );\n"
"var raw = this._db.runCommand( c );\n"
"if ( ! raw.ok )\n"
"throw \"map reduce failed: \" + tojson( raw );\n"
"return new MapReduceResult( this._db , raw );}\n"
"DBCollection.prototype.toString = function(){\n"
"return this.getFullName();}\n"
"DBCollection.prototype.toString = function(){\n"
"return this.getFullName();}\n"
"DBCollection.prototype.tojson = DBCollection.prototype.toString;\n"
"DBCollection.prototype.shellPrint = DBCollection.prototype.toString;\n"
;
比如我们知道可以从db shell中查看当前操作,但是不知道怎么在客户端中实现这个功能,可以找到这个文件中的:
"DB.prototype.currentOp = function(){\n"
"return db.$cmd.sys.inprog.findOne();}\n"
"DB.prototype.currentOP = DB.prototype.currentOp;\n"
"DB.prototype.killOp = function(op) {\n"
"if( !op )\n"
"throw \"no opNum to kill specified\";\n"
"return db.$cmd.sys.killop.findOne({'op':op});}\n"
"DB.prototype.killOP = DB.prototype.killOp;\n"
这几句,我想大家就知道怎么实现了吧。
mongodb是一个好东西,即使和sql server 性能差不多也是好东西(何况性能这么好),因为免费/开源,sql server多贵啊。不过呢,使用nosql还是要看应用的,mongodb的数据基于bson,列名都是重复保存的,所以占用的空间比较大一点,不太适合列数很多的数据,如果要保存日志的话甚至可以除了需要索引的字段都以一个字符串来保存。 |
|