olivier_sk

mongo-hacker .mongorc.js for windows

Mar 2nd, 2014
658
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. mongo_hacker_config = {
  2.     verbose_shell:  true,      // additional verbosity
  3.     index_paranoia: false,     // querytime explain
  4.     enhance_api:    true,      // additonal api extensions
  5.     indent:         4,         // number of spaces for indent
  6.     uuid_type:      'default', // 'java', 'c#', 'python' or 'default'
  7.     banner_message: 'Mongo-Hacker ', //banner message
  8.     version:        '0.0.4',    // current mongo-hacker version
  9.     show_banner:     true,      // show mongo-hacker version banner on startup
  10.  
  11.     // Shell Color Settings
  12.     // Colors available: red, green, yellow, blue, magenta, cyan
  13.     colors: {
  14.         'key':       { color: 'red' },
  15.         'number':    { color: 'yellow' },
  16.         'boolean':   { color: 'magenta', bright: true },
  17.         'null':      { color: 'blue', bright: true },
  18.         'undefined': { color: 'blue', bright: true },
  19.         'objectid':  { color: 'cyan', underline: false },
  20.         'string':    { color: 'green' },
  21.         'binData':   { color: 'green', bright: true },
  22.         'function':  { color: 'magenta' },
  23.         'date':      { color: 'blue' },
  24.         'uuid':      { color: 'cyan' }
  25.     }
  26. }
  27.  
  28. if (mongo_hacker_config['show_banner']) {
  29.     print(mongo_hacker_config['banner_message'] + mongo_hacker_config['version']);
  30. }
  31.  
  32. //----------------------------------------------------------------------------
  33. // Aggregation API Extensions
  34. //----------------------------------------------------------------------------
  35.  
  36. // Inject aggregation extension while supporting base API
  37. DBCollection.prototype.aggregate = function( ops ){
  38.     if (hasDollar(ops) || (ops instanceof Array && hasDollar(ops[0]))){
  39.         var arr = ops;
  40.  
  41.         if (!ops.length) {
  42.             arr = [];
  43.             for (var i=0; i<arguments.length; i++) {
  44.                 arr.push(arguments[i]);
  45.             }
  46.         }
  47.  
  48.         var res = this.runCommand("aggregate", {pipeline: arr});
  49.         if (!res.ok) {
  50.             printStackTrace();
  51.             throw "aggregate failed: " + tojson(res);
  52.         }
  53.         return res;
  54.     } else {
  55.        return new Aggregation( this ).match( ops || {} );
  56.     }
  57. };
  58.  
  59. // Helper method for determining if parameter has dollar signs
  60. function hasDollar(fields){
  61.     for (k in fields){
  62.         if(k.indexOf('$') !== -1){
  63.             return true;
  64.         };
  65.     };
  66.     return false;
  67. }
  68.  
  69. //----------------------------------------------------------------------------
  70. // Aggregation Object
  71. //----------------------------------------------------------------------------
  72. Aggregation = function( collection, fields ){
  73.     this._collection = collection;
  74.     this._pipeline = [];
  75.     this._shellBatchSize = 20;
  76. };
  77.  
  78. Aggregation.prototype.has_next = function() {
  79.     return (this._index < this._results.length);
  80. };
  81.  
  82. Aggregation.prototype.next = function() {
  83.     var next = this._results[this._index];
  84.     this._index += 1;
  85.     return next
  86. };
  87.  
  88. Aggregation.prototype.execute = function() {
  89.     // build the command
  90.     var aggregation = { pipeline: this._pipeline };
  91.     if ( this._readPreference ) {
  92.         aggregation["$readPreference"] = this.readPreference;
  93.     }
  94.  
  95.     // run the command
  96.     var res = this._collection.runCommand(
  97.         "aggregate", aggregation
  98.     );
  99.  
  100.     // check result
  101.     if ( ! res.ok ) {
  102.         printStackTrace();
  103.         throw "aggregation failed: " + tojson(res);
  104.     }
  105.  
  106.     // setup results as pseudo cursor
  107.     this._index = 0;
  108.     this._results = res.result;
  109.  
  110.     return this._results;
  111. };
  112.  
  113. Aggregation.prototype.shellPrint = function() {
  114.     if (this._results == undefined) {
  115.         this.execute();
  116.     }
  117.     try {
  118.         var i = 0;
  119.         while (this.has_next() && i < this._shellBatchSize) {
  120.             var result = this.next();
  121.             printjson( result );
  122.             i++;
  123.         }
  124.         if ( this.has_next() ) {
  125.             print ( "Type \"it\" for more" );
  126.             ___it___ = this;
  127.         }
  128.         else {
  129.             ___it___ = null;
  130.         }
  131.     }
  132.     catch ( e ) {
  133.         print( e );
  134.     }
  135. };
  136.  
  137. Aggregation.prototype.project = function( fields ) {
  138.     if ( ! fields ) {
  139.         throw "project needs fields";
  140.     }
  141.     this._pipeline.push({ "$project": fields });
  142.     return this;
  143. };
  144.  
  145. Aggregation.prototype.find = function( criteria ) {
  146.     if ( ! criteria ) {
  147.         throw "match needs a query object";
  148.     }
  149.     this._pipeline.push({ "$match": criteria });
  150.     return this;
  151. };
  152.  
  153. Aggregation.prototype.match = function( criteria ) {
  154.     if ( ! criteria ) {
  155.         throw "match needs a query object";
  156.     }
  157.     this._pipeline.push({ "$match": criteria });
  158.     return this;
  159. };
  160.  
  161. Aggregation.prototype.limit = function( limit ) {
  162.     if ( ! limit ) {
  163.         throw "limit needs an integer indicating the limit";
  164.     }
  165.     this._pipeline.push({ "$limit": limit });
  166.     return this;
  167. };
  168.  
  169. Aggregation.prototype.skip = function( skip ) {
  170.     if ( ! skip ) {
  171.         throw "skip needs an integer indicating the number to skip";
  172.     }
  173.     this._pipeline.push({ "$skip": skip });
  174.     return this;
  175. };
  176.  
  177. Aggregation.prototype.unwind = function( field ) {
  178.     if ( ! field ) {
  179.         throw "unwind needs the key of an array field to unwind";
  180.     }
  181.     this._pipeline.push({ "$unwind": "$" + field });
  182.     return this;
  183. };
  184.  
  185. Aggregation.prototype.group = function( group_expression ) {
  186.     if ( ! group_expression ) {
  187.         throw "group needs an group expression";
  188.     }
  189.     this._pipeline.push({ "$group": group_expression });
  190.     return this;
  191. };
  192.  
  193. Aggregation.prototype.sort = function( sort ) {
  194.     if ( ! sort ) {
  195.         throw "sort needs a sort document";
  196.     }
  197.     this._pipeline.push({ "$sort": sort });
  198.     return this;
  199. };
  200.  
  201. Aggregation.prototype.geoNear = function( options ) {
  202.     if ( ! options ) {
  203.         throw "geo near requires options"
  204.     }
  205.     this._pipeline.push({ "$geoNear": options });
  206.     return this;
  207. };
  208.  
  209. Aggregation.prototype.readPreference = function( mode ) {
  210.     this._readPreference = mode;
  211.     return this;
  212. };
  213.  
  214. Aggregation.prototype.explain = function() {
  215.     // TODO: https://jira.mongodb.org/browse/SERVER-4504
  216.     throw "not possible yet"
  217. };
  218. //----------------------------------------------------------------------------
  219. // API Additions
  220. //----------------------------------------------------------------------------
  221. DBQuery.prototype.fields = function( fields ) {
  222.     this._fields = fields;
  223.     return this;
  224. };
  225.  
  226. DBQuery.prototype.select = function( fields ){
  227.     this._fields = fields;
  228.     return this;
  229. };
  230.  
  231. DBQuery.prototype.one = function(){
  232.     return this.limit(1)[0];
  233. };
  234.  
  235. DBQuery.prototype.first = function(field){
  236.     var field = field || "$natural";
  237.     var sortBy = {};
  238.     sortBy[field] = 1;
  239.     return this.sort(sortBy).one();
  240. }
  241.  
  242. DBQuery.prototype.reverse = function( field ){
  243.     var field = field || "$natural";
  244.     var sortBy = {};
  245.     sortBy[field] = -1;
  246.     return this.sort(sortBy);
  247. }
  248.  
  249. DBQuery.prototype.last = function( field ){
  250.     var field = field || "$natural";
  251.     return this.reverse(field).one();
  252. }
  253.  
  254. DB.prototype.rename = function(newName) {
  255.     if(newName == this.getName() || newName.length === 0)
  256.         return;
  257.  
  258.     this.copyDatabase(this.getName(), newName, "localhost");
  259.     this.dropDatabase();
  260.     db = this.getSiblingDB(newName);
  261. };
  262.  
  263. //----------------------------------------------------------------------------
  264. // API Modifications (additions and changes)
  265. //----------------------------------------------------------------------------
  266.  
  267. // Add upsert method which has upsert set as true and multi as false
  268. DBQuery.prototype.upsert = function( upsert ){
  269.     assert( upsert , "need an upsert object" );
  270.  
  271.     this._validate(upsert);
  272.     this._db._initExtraInfo();
  273.     this._mongo.update( this._ns , this._query , upsert , true , false );
  274.     this._db._getExtraInfo("Upserted");
  275. };
  276.  
  277. // Updates are always multi and never an upsert
  278. DBQuery.prototype.update = function( update ){
  279.     assert( update , "need an update object" );
  280.  
  281.     this._checkMulti();
  282.     this._validate(update);
  283.     this._db._initExtraInfo();
  284.     this._mongo.update( this._ns , this._query , update , false , true );
  285.     this._db._getExtraInfo("Updated");
  286. };
  287.  
  288. // Replace one document
  289. DBQuery.prototype.replace = function( replacement ){
  290.    assert( replacement , "need an update object" );
  291.  
  292.    this._validate(replacement);
  293.    this._db._initExtraInfo();
  294.    this._mongo.update( this._ns , this._query , replacement , false , false );
  295.    this._db._getExtraInfo("Replaced");
  296. };
  297.  
  298. // Remove is always multi
  299. DBQuery.prototype.remove = function(){
  300.     for ( var k in this._query ){
  301.         if ( k == "_id" && typeof( this._query[k] ) == "undefined" ){
  302.             throw "can't have _id set to undefined in a remove expression";
  303.         }
  304.     }
  305.  
  306.     this._checkMulti();
  307.     this._db._initExtraInfo();
  308.     this._mongo.remove( this._ns , this._query , false );
  309.     this._db._getExtraInfo("Removed");
  310. };
  311.  
  312. //----------------------------------------------------------------------------
  313. // Full Text Search
  314. //----------------------------------------------------------------------------
  315. DBQuery.prototype.textSearch = function( search ) {
  316.     var text = {
  317.         text: this._collection.getName(),
  318.         search: search,
  319.         filter: this._query,
  320.         project: this._fields,
  321.         limit: this._limit
  322.     }
  323.  
  324.     var result = this._db.runCommand( text );
  325.     return result.results;
  326. };function listDbs(){
  327.   return db.adminCommand("listDatabases").databases.map(function(d){return d.name});
  328. }
  329.  
  330. this.__proto__.constructor.autocomplete = listDbs;shellHelper.find = function (query) {
  331.     assert(typeof query == "string");
  332.  
  333.     var args = query.split( /\s+/ );
  334.     query = args[0];
  335.     args = args.splice(1);
  336.  
  337.     if (query !== "") {
  338.         var regexp = new RegExp(query, "i");
  339.         var result = db.runCommand("listCommands");
  340.         for (var command in result.commands) {
  341.             var commandObj = result.commands[command];
  342.             var help = commandObj.help;
  343.             if (commandObj.help.indexOf('\n') != -1 ) {
  344.                 help = commandObj.help.substring(0, commandObj.help.lastIndexOf('\n'));
  345.             }
  346.             if (regexp.test(command) || regexp.test(help)) {
  347.                 var numSpaces = 30 - command.length;
  348.                 print(colorize(command, {color: 'green'}), Array(numSpaces).join(" "), "-", help);
  349.             }
  350.         }
  351.     }
  352. };
  353.  
  354. //----------------------------------------------------------------------------
  355. // Color Functions
  356. //----------------------------------------------------------------------------
  357. __ansi = {
  358.     csi: String.fromCharCode(0x1B) + '[',
  359.     reset: '0',
  360.     text_prop: 'm',
  361.     foreground: '3',
  362.     bright: '1',
  363.     underline: '4',
  364.  
  365.     colors: {
  366.         red: '1',
  367.         green: '2',
  368.         yellow: '3',
  369.         blue: '4',
  370.         magenta: '5',
  371.         cyan: '6'
  372.     }
  373. };
  374.  
  375. function controlCode( parameters ) {
  376.     if ( parameters === undefined ) {
  377.         parameters = "";
  378.     }
  379.     else if (typeof(parameters) == 'object' && (parameters instanceof Array)) {
  380.         parameters = parameters.join(';');
  381.     }
  382.  
  383.     return __ansi.csi + String(parameters) + String(__ansi.text_prop);
  384. };
  385.  
  386. function applyColorCode( string, properties ) {
  387.     return controlCode(properties) + String(string) + controlCode();
  388. };
  389.  
  390. function colorize( string, color ) {
  391.     var params = [];
  392.     var code = __ansi.foreground + __ansi.colors[color.color];
  393.  
  394.     params.push(code);
  395.  
  396.     if ( color.bright === true ) params.push(__ansi.bright);
  397.     if ( color.underline === true ) params.push(__ansi.underline);
  398.  
  399.     return applyColorCode( string, params );
  400. };
  401. __indent = Array(mongo_hacker_config.indent + 1).join(' ');
  402.  
  403. ObjectId.prototype.toString = function() {
  404.     return this.str;
  405. };
  406.  
  407. ObjectId.prototype.tojson = function(indent, nolint) {
  408.     return tojson(this);
  409. };
  410.  
  411. var dateToJson = Date.prototype.tojson;
  412.  
  413. Date.prototype.tojson = function() {
  414.   var isoDateString = dateToJson.call(this);
  415.   var dateString = isoDateString.substring(8, isoDateString.length-1);
  416.  
  417.   var isodate = colorize(dateString, mongo_hacker_config.colors.date);
  418.   return 'ISODate(' + isodate + ')';
  419. };
  420.  
  421. Array.tojson = function( a , indent , nolint ){
  422.     var lineEnding = nolint ? " " : "\n";
  423.  
  424.     if (!indent)
  425.         indent = "";
  426.  
  427.     if ( nolint )
  428.         indent = "";
  429.  
  430.     if (a.length === 0) {
  431.         return "[ ]";
  432.     }
  433.  
  434.     var s = "[" + lineEnding;
  435.     indent += __indent;
  436.     for ( var i=0; i<a.length; i++){
  437.         s += indent + tojson( a[i], indent , nolint );
  438.         if ( i < a.length - 1 ){
  439.             s += "," + lineEnding;
  440.         }
  441.     }
  442.     if ( a.length === 0 ) {
  443.         s += indent;
  444.     }
  445.  
  446.     indent = indent.substring(__indent.length);
  447.     s += lineEnding+indent+"]";
  448.     return s;
  449. };
  450.  
  451. function surround(name, inside) {
  452.     return [name, '(', inside, ')'].join('');
  453. }
  454.  
  455. NumberLong.prototype.tojson = function() {
  456.     var color = mongo_hacker_config.colors.number;
  457.     var output = colorize('"' + this.toString().match(/-?\d+/)[0] + '"', color);
  458.     return surround('NumberLong', output);
  459. };
  460.  
  461. NumberInt.prototype.tojson = function() {
  462.     var color = mongo_hacker_config.colors.number;
  463.     var output = colorize('"' + this.toString().match(/-?\d+/)[0] + '"', color);
  464.     return surround('NumberInt', output);
  465. };
  466.  
  467. BinData.prototype.tojson = function(indent , nolint) {
  468.     var uuidType = mongo_hacker_config.uuid_type;
  469.     var uuidColor = mongo_hacker_config.colors.uuid;
  470.     var binDataColor = mongo_hacker_config.colors.binData;
  471.  
  472.     if (this.subtype() === 3) {
  473.         var ouput = colorize('"' + uuidToString(this) + '"', color) + ', '
  474.         output += colorize('"' + uuidType + '"', uuidColor)
  475.         return surround('UUID', output);
  476.     } else if (this.subtype() === 4) {
  477.         var output = colorize('"' + uuidToString(this, "default") + '"', uuidColor) + ')'
  478.         return surround('UUID', output);
  479.     } else {
  480.         var output = colorize(this.subtype(), {color: 'red'}) + ', '
  481.         output += colorize('"' + this.base64() + '"', binDataColor)
  482.         return surround('BinData', output);
  483.     }
  484. };
  485.  
  486. DBQuery.prototype.shellPrint = function(){
  487.     try {
  488.         var start = new Date().getTime();
  489.         var n = 0;
  490.         while ( this.hasNext() && n < DBQuery.shellBatchSize ){
  491.             var s = this._prettyShell ? tojson( this.next() ) : tojson( this.next() , "" , true );
  492.             print( s );
  493.             n++;
  494.         }
  495.  
  496.         var output = [];
  497.  
  498.         if (typeof _verboseShell !== 'undefined' && _verboseShell) {
  499.             var time = new Date().getTime() - start;
  500.             var slowms = getSlowms();
  501.             var fetched = "Fetched " + n + " record(s) in ";
  502.             if (time > slowms) {
  503.                 fetched += colorize(time + "ms", { color: "red", bright: true });
  504.             } else {
  505.                 fetched += colorize(time + "ms", { color: "green", bright: true });
  506.             }
  507.             output.push(fetched);
  508.         }
  509.  
  510.         var paranoia = mongo_hacker_config.index_paranoia;
  511.  
  512.         if (typeof paranoia !== 'undefined' && paranoia) {
  513.             var explain = this.clone();
  514.             explain._ensureSpecial();
  515.             explain._query.$explain = true;
  516.             explain._limit = Math.abs(n._limit) * -1;
  517.             var result = explain.next();
  518.             var type = result.cursor;
  519.  
  520.             if (type !== undefined) {
  521.                 var index_use = "Index[";
  522.                 if (type == "BasicCursor") {
  523.                     index_use += colorize( "none", { color: "red", bright: true });
  524.                 } else {
  525.                     index_use += colorize( result.cursor.substring(12), { color: "green", bright: true });
  526.                 }
  527.                 index_use += "]";
  528.                 output.push(index_use);
  529.             }
  530.         }
  531.  
  532.         if ( this.hasNext() ) {
  533.             ___it___  = this;
  534.             output.push("More[" + colorize("true", { color: "green", bright: true }) + "]");
  535.         }
  536.         print(output.join(" -- "));
  537.     }
  538.     catch ( e ){
  539.         print( e );
  540.     }
  541. };
  542.  
  543. tojsonObject = function( x, indent, nolint ) {
  544.     var lineEnding = nolint ? " " : "\n";
  545.     var tabSpace = nolint ? "" : __indent;
  546.  
  547.     assert.eq( ( typeof x ) , "object" , "tojsonObject needs object, not [" + ( typeof x ) + "]" );
  548.  
  549.     if (!indent)
  550.         indent = "";
  551.  
  552.     if ( typeof( x.tojson ) == "function" && x.tojson != tojson ) {
  553.         return x.tojson(indent,nolint);
  554.     }
  555.  
  556.     if ( x.constructor && typeof( x.constructor.tojson ) == "function" && x.constructor.tojson != tojson ) {
  557.         return x.constructor.tojson( x, indent , nolint );
  558.     }
  559.  
  560.     if ( x.toString() == "[object MaxKey]" )
  561.         return "{ $maxKey : 1 }";
  562.     if ( x.toString() == "[object MinKey]" )
  563.         return "{ $minKey : 1 }";
  564.  
  565.     var s = "{" + lineEnding;
  566.  
  567.     // push one level of indent
  568.     indent += tabSpace;
  569.  
  570.     var total = 0;
  571.     for ( var k in x ) total++;
  572.     if ( total === 0 ) {
  573.         s += indent + lineEnding;
  574.     }
  575.  
  576.     var keys = x;
  577.     if ( typeof( x._simpleKeys ) == "function" )
  578.         keys = x._simpleKeys();
  579.     var num = 1;
  580.     for ( var key in keys ){
  581.  
  582.         var val = x[key];
  583.         if ( val == DB.prototype || val == DBCollection.prototype )
  584.             continue;
  585.  
  586.         var color = mongo_hacker_config.colors.key;
  587.         s += indent + colorize("\"" + key + "\"", color) + ": " + tojson( val, indent , nolint );
  588.         if (num != total) {
  589.             s += ",";
  590.             num++;
  591.         }
  592.         s += lineEnding;
  593.     }
  594.  
  595.     // pop one level of indent
  596.     indent = indent.substring(__indent.length);
  597.     return s + indent + "}";
  598. };
  599.  
  600.  
  601. tojson = function( x, indent , nolint ) {
  602.     if ( x === null )
  603.         return colorize("null", mongo_hacker_config.colors['null']);
  604.  
  605.     if ( x === undefined )
  606.         return colorize("undefined", mongo_hacker_config.colors['undefined']);
  607.  
  608.     if ( x.isObjectId ) {
  609.         var color = mongo_hacker_config.colors['objectid'];
  610.         return surround('ObjectId', colorize('"' + x.str + '"', color));
  611.     }
  612.  
  613.     if (!indent)
  614.         indent = "";
  615.  
  616.     var s;
  617.     switch ( typeof x ) {
  618.     case "string": {
  619.         s = "\"";
  620.         for ( var i=0; i<x.length; i++ ){
  621.             switch (x[i]){
  622.                 case '"': s += '\\"'; break;
  623.                 case '\\': s += '\\\\'; break;
  624.                 case '\b': s += '\\b'; break;
  625.                 case '\f': s += '\\f'; break;
  626.                 case '\n': s += '\\n'; break;
  627.                 case '\r': s += '\\r'; break;
  628.                 case '\t': s += '\\t'; break;
  629.  
  630.                 default: {
  631.                     var code = x.charCodeAt(i);
  632.                     if (code < 0x20){
  633.                         s += (code < 0x10 ? '\\u000' : '\\u00') + code.toString(16);
  634.                     } else {
  635.                         s += x[i];
  636.                     }
  637.                 }
  638.             }
  639.         }
  640.         s += "\"";
  641.         return colorize(s, mongo_hacker_config.colors.string);
  642.     }
  643.     case "number":
  644.         return colorize(x, mongo_hacker_config.colors.number);
  645.     case "boolean":
  646.         return colorize("" + x, mongo_hacker_config.colors['boolean']);
  647.     case "object": {
  648.         s = tojsonObject( x, indent , nolint );
  649.         if ( ( nolint === null || nolint === true ) && s.length < 80 && ( indent === null || indent.length === 0 ) ){
  650.             s = s.replace( /[\s\r\n ]+/gm , " " );
  651.         }
  652.         return s;
  653.     }
  654.     case "function":
  655.         return colorize(x.toString(), mongo_hacker_config.colors['function']);
  656.     default:
  657.         throw "tojson can't handle type " + ( typeof x );
  658.     }
  659.  
  660. };
  661.  
  662.  
  663. DBQuery.prototype._validate = function( o ){
  664.     var firstKey = null;
  665.     for (var k in o) { firstKey = k; break; }
  666.  
  667.     if (firstKey !== null && firstKey[0] == '$') {
  668.         // for mods we only validate partially, for example keys may have dots
  669.         this._validateObject( o );
  670.     } else {
  671.         // we're basically inserting a brand new object, do full validation
  672.         this._validateForStorage( o );
  673.     }
  674. };
  675.  
  676. DBQuery.prototype._validateObject = function( o ){
  677.     if (typeof(o) != "object")
  678.         throw "attempted to save a " + typeof(o) + " value.  document expected.";
  679.  
  680.     if ( o._ensureSpecial && o._checkModify )
  681.         throw "can't save a DBQuery object";
  682. };
  683.  
  684. DBQuery.prototype._validateForStorage = function( o ){
  685.     this._validateObject( o );
  686.     for ( var k in o ){
  687.         if ( k.indexOf( "." ) >= 0 ) {
  688.             throw "can't have . in field names [" + k + "]" ;
  689.         }
  690.  
  691.         if ( k.indexOf( "$" ) === 0 && ! DBCollection._allowedFields[k] ) {
  692.             throw "field names cannot start with $ [" + k + "]";
  693.         }
  694.  
  695.         if ( o[k] !== null && typeof( o[k] ) === "object" ) {
  696.             this._validateForStorage( o[k] );
  697.         }
  698.     }
  699. };
  700.  
  701. DBQuery.prototype._checkMulti = function(){
  702.   if(this._limit > 0 || this._skip > 0){
  703.     var ids = this.clone().select({_id: 1}).map(function(o){return o._id;});
  704.     this._query['_id'] = {'$in': ids};
  705.     return true;
  706.   } else {
  707.     return false;
  708.   }
  709. };
  710.  
  711. DBQuery.prototype.ugly = function(){
  712.     this._prettyShell = false;
  713.     return this;
  714. }
  715.  
  716. DB.prototype.shutdownServer = function(opts) {
  717.     if( "admin" != this._name ){
  718.         return "shutdown command only works with the admin database; try 'use admin'";
  719.     }
  720.  
  721.     cmd = {"shutdown" : 1};
  722.     opts = opts || {};
  723.     for (var o in opts) {
  724.         cmd[o] = opts[o];
  725.     }
  726.  
  727.     try {
  728.         var res = this.runCommand(cmd);
  729.         if( res )
  730.             throw "shutdownServer failed: " + res.errmsg;
  731.         throw "shutdownServer failed";
  732.     }
  733.     catch ( e ){
  734.         assert( e.message.indexOf( "error doing query: failed" ) >= 0 , "unexpected error: " + tojson( e ) );
  735.         print( "server should be down..." );
  736.     }
  737. }
  738. //----------------------------------------------------------------------------
  739. // findAndModify Helper
  740. //----------------------------------------------------------------------------
  741. DBQuery.prototype._findAndModify = function( options ) {
  742.     var findAndModify = {
  743.         'findandmodify': this._collection.getName(),
  744.         'query': this._query,
  745.         'new': true,
  746.         'fields': this._fields,
  747.         'upsert': this._upsert || false,
  748.         'sort': this._query.orderby || {},
  749.     };
  750.  
  751.     for (var key in options){
  752.         findAndModify[key] = options[key];
  753.     };
  754.  
  755.     var result = this._db.runCommand( findAndModify );
  756.     if ( ! result.ok ){
  757.         throw "findAndModifyFailed failed: " + tojson( result );
  758.     };
  759.     return result.value;
  760. };
  761.  
  762. //----------------------------------------------------------------------------
  763. // findAndModify Terminal Variants
  764. //----------------------------------------------------------------------------
  765. DBQuery.prototype.updateAndGet = function( update ) {
  766.     return this._findAndModify({ 'update': update });
  767. };
  768.  
  769. DBQuery.prototype.getAndUpdate = function( update ) {
  770.     return this._findAndModify({ 'update': update, 'new': false });
  771. };
  772.  
  773. DBQuery.prototype.replaceAndGet = function( replacement ) {
  774.     return this._findAndModify({ 'update': replacement });
  775. };
  776.  
  777. DBQuery.prototype.getAndReplace = function( replacement ) {
  778.     return this._findAndModify({ 'update': replacement, 'new': false });
  779. };
  780.  
  781. DBQuery.prototype.getAndRemove = function() {
  782.     return this._findAndModify({ 'remove': true })
  783. };function runMatch(cmd, args, regexp) {
  784.     clearRawMongoProgramOutput();
  785.     if (args) {
  786.         run(cmd, args);
  787.     } else {
  788.         run(cmd);
  789.     }
  790.     var output = rawMongoProgramOutput();
  791.     return output.match(regexp);
  792. };
  793.  
  794. function getEnv(env_var) {
  795.     var env_regex = new RegExp(' ' + env_var + '=(.*)');
  796.     return runMatch('env', '', env_regex)[1];
  797. };
  798.  
  799. function getVersion() {
  800.     var regexp = /version: (\d).(\d).(\d)/;
  801.     return runMatch('mongo', '--version', regexp).slice(1, 4);
  802. };
  803.  
  804. function isMongos() {
  805.     return db.isMaster().msg == 'isdbgrid';
  806. };
  807.  
  808. function getSlowms(){
  809.     if(!isMongos()){
  810.         return db.getProfilingStatus().slowms;
  811.     } else {
  812.         return 100;
  813.     }
  814. };
  815. // Override group because map/reduce style is deprecated
  816. DBCollection.prototype.agg_group = function( name, group_field, operation, op_value, filter ) {
  817.     var ops = [];
  818.     var group_op = { $group: { _id: '$' + group_field } };
  819.  
  820.     if (filter !== undefined) {
  821.         ops.push({ '$match': filter });
  822.     }
  823.  
  824.     group_op['$group'][name] = { };
  825.     group_op['$group'][name]['$' + operation] = op_value;
  826.     ops.push(group_op);
  827.  
  828.     return this.aggregate(ops);
  829. };
  830.  
  831. // Function that groups and counts by group after applying filter
  832. DBCollection.prototype.gcount = function( group_field, filter ) {
  833.     return this.agg_group('count', group_field, 'sum', 1, filter);
  834. };
  835.  
  836. // Function that groups and sums sum_field after applying filter
  837. DBCollection.prototype.gsum = function( group_field, sum_field, filter ) {
  838.     return this.agg_group('sum', group_field, 'sum', '$' + sum_field, filter);
  839. };
  840.  
  841. // Function that groups and averages avg_feld after applying filter
  842. DBCollection.prototype.gavg = function( group_field, avg_field, filter ) {
  843.     return this.agg_group('avg', group_field, 'avg', '$' + avg_field, filter);
  844. };
  845. // Improve the default prompt with hostname, process type, and version
  846. prompt = function() {
  847.     var serverstatus = db.serverStatus();
  848.     var host = serverstatus.host.split('.')[0];
  849.     var process = serverstatus.process;
  850.     var version = db.serverBuildInfo().version;
  851.     var repl_set = db._adminCommand({"replSetGetStatus": 1}).ok !== 0;
  852.     var rs_state = '';
  853.     if(repl_set) {
  854.         members = rs.status().members;
  855.         for(var i = 0; i<members.length; i++){
  856.             if(members[i].self === true){
  857.                 rs_state = '[' + members[i].stateStr + ']';
  858.             }
  859.         };
  860.     }
  861.     var state = isMongos() ? '[mongos]' : rs_state;
  862.     return host + '(' + process + '-' + version + ')' + state + ' ' + db + '> ';
  863. };
  864.  
  865. // Better show dbs
  866. shellHelper.show = function (what) {
  867.     assert(typeof what == "string");
  868.  
  869.     var args = what.split( /\s+/ );
  870.     what = args[0]
  871.     args = args.splice(1)
  872.  
  873.     if (what == "profile") {
  874.         if (db.system.profile.count() == 0) {
  875.             print("db.system.profile is empty");
  876.             print("Use db.setProfilingLevel(2) will enable profiling");
  877.             print("Use db.system.profile.find() to show raw profile entries");
  878.         }
  879.         else {
  880.             print();
  881.             db.system.profile.find({ millis: { $gt: 0} }).sort({ $natural: -1 }).limit(5).forEach(
  882.                 function (x) {
  883.                     print("" + x.op + "\t" + x.ns + " " + x.millis + "ms " + String(x.ts).substring(0, 24));
  884.                     var l = "";
  885.                     for ( var z in x ){
  886.                         if ( z == "op" || z == "ns" || z == "millis" || z == "ts" )
  887.                             continue;
  888.  
  889.                         var val = x[z];
  890.                         var mytype = typeof(val);
  891.  
  892.                         if ( mytype == "string" ||
  893.                              mytype == "number" )
  894.                             l += z + ":" + val + " ";
  895.                         else if ( mytype == "object" )
  896.                             l += z + ":" + tojson(val ) + " ";
  897.                         else if ( mytype == "boolean" )
  898.                             l += z + " ";
  899.                         else
  900.                             l += z + ":" + val + " ";
  901.  
  902.                     }
  903.                     print( l );
  904.                     print("\n");
  905.                 }
  906.             )
  907.         }
  908.         return "";
  909.     }
  910.  
  911.     if (what == "users") {
  912.         db.system.users.find().forEach(printjson);
  913.         return "";
  914.     }
  915.  
  916.     if (what == "collections" || what == "tables") {
  917.         var maxNameLength = 0;
  918.         var paddingLength = 2;
  919.         db.getCollectionNames().forEach(function (collectionName) {
  920.           if (collectionName.length > maxNameLength) {
  921.             maxNameLength = collectionName.length;
  922.           }
  923.         });
  924.         db.getCollectionNames().forEach(function (collectionName) {
  925.           var stats = db[collectionName].stats();
  926.           while(collectionName.length < maxNameLength + paddingLength)
  927.             collectionName = collectionName + " ";
  928.           var size = (stats.size / 1024 / 1024).toFixed(3),
  929.               storageSize = (stats.storageSize / 1024 / 1024).toFixed(3);
  930.  
  931.           print(colorize(collectionName, { color: 'green', bright: true }) + size + "MB / " + storageSize + "MB")
  932.         });
  933.         return "";
  934.     }
  935.  
  936.     if (what == "dbs" || what == "databases") {
  937.         var dbs = db.getMongo().getDBs();
  938.         var dbinfo = [];
  939.         var maxNameLength = 0;
  940.         var maxGbDigits = 0;
  941.  
  942.         dbs.databases.forEach(function (x){
  943.             var sizeStr = (x.sizeOnDisk / 1024 / 1024 / 1024).toFixed(3);
  944.             var nameLength = x.name.length;
  945.             var gbDigits = sizeStr.indexOf(".");
  946.  
  947.             if( nameLength > maxNameLength) maxNameLength = nameLength;
  948.             if( gbDigits > maxGbDigits ) maxGbDigits = gbDigits;
  949.  
  950.             dbinfo.push({
  951.                 name:      x.name,
  952.                 size:      x.sizeOnDisk,
  953.                 size_str:  sizeStr,
  954.                 name_size: nameLength,
  955.                 gb_digits: gbDigits
  956.             });
  957.         });
  958.  
  959.         dbinfo.sort(function (a,b) { a.name - b.name });
  960.         dbinfo.forEach(function (db) {
  961.             var namePadding = maxNameLength - db.name_size;
  962.             var sizePadding = maxGbDigits   - db.gb_digits;
  963.             var padding = Array(namePadding + sizePadding + 3).join(" ");
  964.             if (db.size > 1) {
  965.                 print(colorize(db.name, { color: 'green', bright: true }) + padding + db.size_str + "GB");
  966.             } else {
  967.                 print(colorize(db.name, { color: 'green', bright: true }) + padding + "(empty)");
  968.             }
  969.         });
  970.  
  971.         return "";
  972.     }
  973.  
  974.     if (what == "log" ) {
  975.         var n = "global";
  976.         if ( args.length > 0 )
  977.             n = args[0]
  978.  
  979.         var res = db.adminCommand( { getLog : n } );
  980.         if ( ! res.ok ) {
  981.             print("Error while trying to show " + n + " log: " + res.errmsg);
  982.             return "";
  983.         }
  984.         for ( var i=0; i<res.log.length; i++){
  985.             print( res.log[i] )
  986.         }
  987.         return ""
  988.     }
  989.  
  990.     if (what == "logs" ) {
  991.         var res = db.adminCommand( { getLog : "*" } )
  992.         if ( ! res.ok ) {
  993.             print("Error while trying to show logs: " + res.errmsg);
  994.             return "";
  995.         }
  996.         for ( var i=0; i<res.names.length; i++){
  997.             print( res.names[i] )
  998.         }
  999.         return ""
  1000.     }
  1001.  
  1002.     if (what == "startupWarnings" ) {
  1003.         var dbDeclared, ex;
  1004.         try {
  1005.             // !!db essentially casts db to a boolean
  1006.             // Will throw a reference exception if db hasn't been declared.
  1007.             dbDeclared = !!db;
  1008.         } catch (ex) {
  1009.             dbDeclared = false;
  1010.         }
  1011.         if (dbDeclared) {
  1012.             var res = db.adminCommand( { getLog : "startupWarnings" } );
  1013.             if ( res.ok ) {
  1014.                 if (res.log.length == 0) {
  1015.                     return "";
  1016.                 }
  1017.                 print( "Server has startup warnings: " );
  1018.                 for ( var i=0; i<res.log.length; i++){
  1019.                     print( res.log[i] )
  1020.                 }
  1021.                 return "";
  1022.             } else if (res.errmsg == "unauthorized") {
  1023.                 // Don't print of startupWarnings command failed due to auth
  1024.                 return "";
  1025.             } else {
  1026.                 print("Error while trying to show server startup warnings: " + res.errmsg);
  1027.                 return "";
  1028.             }
  1029.         } else {
  1030.             print("Cannot show startupWarnings, \"db\" is not set");
  1031.             return "";
  1032.         }
  1033.     }
  1034.  
  1035.     throw "don't know how to show [" + what + "]";
  1036.  
  1037. }
  1038. printShardingStatus = function( configDB , verbose ){
  1039.     if (configDB === undefined)
  1040.         configDB = db.getSisterDB('config')
  1041.  
  1042.     var version = configDB.getCollection( "version" ).findOne();
  1043.     if ( version == null ){
  1044.         print( "printShardingStatus: this db does not have sharding enabled. be sure you are connecting to a mongos from the shell and not to a mongod." );
  1045.         return;
  1046.     }
  1047.  
  1048.     var raw = "";
  1049.     var output = function(s){
  1050.         raw += s + "\n";
  1051.     }
  1052.     output( "--- Sharding Status --- " );
  1053.     output( "  sharding version: " + tojson( configDB.getCollection( "version" ).findOne(), "  " ) );
  1054.  
  1055.     output( "  shards:" );
  1056.     configDB.shards.find().sort( { _id : 1 } ).forEach(
  1057.         function(z){
  1058.             output( "    " + tojsononeline( z ) );
  1059.         }
  1060.     );
  1061.  
  1062.     output( "  databases:" );
  1063.     configDB.databases.find().sort( { name : 1 } ).forEach(
  1064.         function(db){
  1065.             output( "    " + tojsononeline(db,"",true) );
  1066.  
  1067.             if (db.partitioned){
  1068.                 configDB.collections.find( { _id : new RegExp( "^" +
  1069.                     RegExp.escape(db._id) + "\\." ) } ).
  1070.                     sort( { _id : 1 } ).forEach( function( coll ){
  1071.                         if ( coll.dropped == false ){
  1072.                             output( "    " + coll._id );
  1073.                             output( "      shard key: " + tojson(coll.key, 0, true) );
  1074.                             output( "      chunks:" );
  1075.  
  1076.                             res = configDB.chunks.aggregate(
  1077.                                 { "$match": { ns: coll._id } },
  1078.                                 { "$group": { _id: "$shard", nChunks: { "$sum": 1 } } }
  1079.                             ).result
  1080.  
  1081.                             var totalChunks = 0;
  1082.                             res.forEach( function(z){
  1083.                                 totalChunks += z.nChunks;
  1084.                                 output( "        " + z._id + ": " + z.nChunks );
  1085.                             } )
  1086.  
  1087.                             if ( totalChunks < 20 || verbose ){
  1088.                                 configDB.chunks.find( { "ns" : coll._id } ).sort( { min : 1 } ).forEach(
  1089.                                     function(chunk){
  1090.                                         output( "        " +
  1091.                                             tojson( chunk.min, 0, true) + " -> " +
  1092.                                             tojson( chunk.max, 0, true ) +
  1093.                                             " on: " + colorize(chunk.shard, {color: 'cyan'}) + " " +
  1094.                                             ( chunk.jumbo ? "jumbo " : "" )
  1095.                                         );
  1096.                                     }
  1097.                                 );
  1098.                             }
  1099.                             else {
  1100.                                 output( "\t\t\ttoo many chunks to print, use verbose if you want to force print" );
  1101.                             }
  1102.  
  1103.                             configDB.tags.find( { ns : coll._id } ).sort( { min : 1 } ).forEach(
  1104.                                 function( tag ) {
  1105.                                     output( "        tag: " + tag.tag + "  " + tojson( tag.min ) + " -> " + tojson( tag.max ) );
  1106.                                 }
  1107.                             )
  1108.                         }
  1109.                     }
  1110.                 )
  1111.             }
  1112.         }
  1113.     );
  1114.  
  1115.     print( raw );
  1116. }
  1117. function base64ToHex(base64) {
  1118.     var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  1119.     var hexDigits = "0123456789abcdef";
  1120.     var hex = "";
  1121.     for (var i = 0; i < 24; ) {
  1122.         var e1 = base64Digits.indexOf(base64[i++]);
  1123.         var e2 = base64Digits.indexOf(base64[i++]);
  1124.         var e3 = base64Digits.indexOf(base64[i++]);
  1125.         var e4 = base64Digits.indexOf(base64[i++]);
  1126.         var c1 = (e1 << 2) | (e2 >> 4);
  1127.         var c2 = ((e2 & 15) << 4) | (e3 >> 2);
  1128.         var c3 = ((e3 & 3) << 6) | e4;
  1129.         hex += hexDigits[c1 >> 4];
  1130.         hex += hexDigits[c1 & 15];
  1131.         if (e3 != 64) {
  1132.             hex += hexDigits[c2 >> 4];
  1133.             hex += hexDigits[c2 & 15];
  1134.         }
  1135.         if (e4 != 64) {
  1136.             hex += hexDigits[c3 >> 4];
  1137.             hex += hexDigits[c3 & 15];
  1138.         }
  1139.     }
  1140.     return hex;
  1141. }
  1142.  
  1143. function hexToBase64(hex) {
  1144.     var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  1145.     var base64 = "";
  1146.     var group;
  1147.     for (var i = 0; i < 30; i += 6) {
  1148.         group = parseInt(hex.substr(i, 6), 16);
  1149.         base64 += base64Digits[(group >> 18) & 0x3f];
  1150.         base64 += base64Digits[(group >> 12) & 0x3f];
  1151.         base64 += base64Digits[(group >> 6) & 0x3f];
  1152.         base64 += base64Digits[group & 0x3f];
  1153.     }
  1154.     group = parseInt(hex.substr(30, 2), 16);
  1155.     base64 += base64Digits[(group >> 2) & 0x3f];
  1156.     base64 += base64Digits[(group << 4) & 0x3f];
  1157.     base64 += "==";
  1158.     return base64;
  1159. }
  1160.  
  1161. var platformSpecificUuidModifications = {
  1162.     "java": function (hex) {
  1163.         var msb = hex.substr(0, 16);
  1164.         var lsb = hex.substr(16, 16);
  1165.         msb = msb.substr(14, 2) + msb.substr(12, 2) + msb.substr(10, 2) + msb.substr(8, 2)
  1166.             + msb.substr(6, 2) + msb.substr(4, 2) + msb.substr(2, 2) + msb.substr(0, 2);
  1167.         lsb = lsb.substr(14, 2) + lsb.substr(12, 2) + lsb.substr(10, 2) + lsb.substr(8, 2)
  1168.             + lsb.substr(6, 2) + lsb.substr(4, 2) + lsb.substr(2, 2) + lsb.substr(0, 2);
  1169.         return msb + lsb;
  1170.     },
  1171.     "c#": function (hex) {
  1172.         return hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2)
  1173.             + hex.substr(10, 2) + hex.substr(8, 2) + hex.substr(14, 2) + hex.substr(12, 2)
  1174.             + hex.substr(16, 16);
  1175.     },
  1176.     "python": function (hex) {
  1177.         return hex;
  1178.     },
  1179.     "default": function (hex) {
  1180.         return hex;
  1181.     }
  1182. };
  1183.  
  1184. function UUID(uuid, type) {
  1185.     var hex = uuid.replace(/[{}-]/g, "");
  1186.     var typeNum = 4;
  1187.     if (type != undefined) {
  1188.         typeNum = 3;
  1189.         hex = platformSpecificUuidModifications[type](hex);
  1190.     }
  1191.     return new BinData(typeNum, hexToBase64(hex));
  1192. }
  1193.  
  1194. function uuidToString(uuid, uuidType) {
  1195.     var uuidType = uuidType || mongo_hacker_config['uuid_type'];
  1196.     var hex = platformSpecificUuidModifications[uuidType](base64ToHex(uuid.base64()));
  1197.     return hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4)
  1198.         + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
  1199. }
  1200. setVerboseShell(true);
  1201.  
  1202. DBQuery.prototype._prettyShell = true
  1203.  
  1204. DB.prototype._getExtraInfo = function(action) {
  1205.     if ( typeof _verboseShell === 'undefined' || !_verboseShell ) {
  1206.         __callLastError = true;
  1207.         return;
  1208.     }
  1209.  
  1210.     // explicit w:1 so that replset getLastErrorDefaults aren't used here which would be bad.
  1211.     var startTime = new Date().getTime();
  1212.     var res = this.getLastErrorCmd(1);
  1213.     if (res) {
  1214.         if (res.err !== undefined && res.err !== null) {
  1215.             // error occurred, display it
  1216.             print(res.err);
  1217.             return;
  1218.         }
  1219.  
  1220.         var info = action + " ";
  1221.         // hack for inserted because res.n is 0
  1222.         info += action != "Inserted" ? res.n : 1;
  1223.         if (res.n > 0 && res.updatedExisting !== undefined) info += " " + (res.updatedExisting ? "existing" : "new");
  1224.         info += " record(s) in ";
  1225.         var time = new Date().getTime() - startTime;
  1226.         var slowms = getSlowms();
  1227.         if (time > slowms) {
  1228.             info += colorize(time + "ms", { color: 'red', bright: true });
  1229.         } else {
  1230.             info += colorize(time + "ms", { color: 'green', bright: true });
  1231.         }
  1232.         print(info);
  1233.     }
  1234. };
Add Comment
Please, Sign In to add comment