Mongo shellの裏技色々

MongoDBを扱う上で避けては通れないmongo shell (mongo コマンド)

実はV8搭載の強力な実行環境です。

使い倒さなきゃ勿体無い！！！

MongoDBの小技を覚えておけばグンと使いやすくなりますよ。

## １．各DBの負荷状況
運用では普通に使えます。
下記のloadで独自のユーティリティファイルを使いJSで解析してしまうと楽。

```js
> use admin
> db.runCommand({top:1})
{
        "totals" : {
                "note" : "all times in microseconds",
                "admin" : {
                        "total" : {
                                "time" : 7,
                                "count" : 1
                        },
                        "readLock" : {
                                "time" : 0,
                                "count" : 0
                        },
                        "writeLock" : {
                                "time" : 7,
                                "count" : 1
                        },
                        "queries" : {
                                "time" : 7,
                                "count" : 1
                        },
                        "getmore" : {
                                "time" : 0,
                                "count" : 0
                        },
                        "insert" : {
                                "time" : 0,
                                "count" : 0
                        },
                        "update" : {
                                "time" : 0,
                                "count" : 0
                        },
                        "remove" : {
                                "time" : 0,
                                "count" : 0
                        },
                        "commands" : {
                                "time" : 0,
                                "count" : 0
                        }
                },
                "admin.system.indexes" : {
                        "total" : {
  :
  :
}
```
## ２．別DBへのコネクションを扱う
複数のDB、コレクション、別mongoへのコネクションなどは、変数に格納しておくと便利。

```js
> conn2test_db = connect('192.168.xxx.xx:27017/test')
connecting to: 192.168.xxx.xx:27017/test
test
> conn2test_db.getCollectionNames()
[ "system.indexes", "test", "test2"]
> conn2test_test2 = conn2test_db.getCollection('test2')
test.test2
> conn2test_test2.findOne()
{ .... }
```
## ３．mongodの情報
良くわからん環境を調査（泣）しなきゃならない時にまず発行・・・

```js
> db.hostInfo()
{
        "system" : {
                "currentTime" : ISODate("2013-12-03T14:42:31.074Z"),
                "hostname" : "xxxxxxxxx",
                "cpuAddrSize" : 64,
                "memSizeMB" : 1877,
                "numCores" : 3,
                "cpuArch" : "x86_64",
                "numaEnabled" : false
        },
        "os" : {
                "type" : "Linux",
                "name" : "",
                "version" : ""
        },
        "extra" : {
                "versionString" : "Linux version 2.6.32-358.11.1.el6.x86_64 (mockbuild@c6b7.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) ) #1 SMP Wed Jun 12 03:34:52 UTC 2013",
                "libcVersion" : "2.12",
                "kernelVersion" : "2.6.32-358.11.1.el6.x86_64",
                "cpuFrequencyMHz" : "2500.050",
                "cpuFeatures" : "fpu de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm constant_tsc arch_perfmon unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt aes xsave avx hypervisor xsaveopt",
                "pageSize" : NumberLong(4096),
                "numPages" : 480610,
                "maxOpenFiles" : 65535
        },
        "ok" : 1
}
```

## ４．Mongo shell の使用メモリ
ある程度の解析をshell上でやってしまう場合に参考になります。

```js
> getMemInfo()
{ "virtual" : 598, "resident" : 15 }
```

## ５．mongodが抱えてるコネクションと自分のコネクション
こいつらを付き合わせると、zookeeperの様な生存チェックができる。
### 自分のコネクション

```js
> db.runCommand({whatsmyuri:1})
{ "you" : "133.242.166.78:35590", "ok" : 1 }
```
### ６．mongodが抱えてるコネクション
clientフィールドと比較する

```js
> db.$cmd.sys.inprog.findOne({ $all : true })
{
        "inprog" : [
                {
                        "opid" : 6,
                        "active" : false,
                        "op" : "insert",
                        "ns" : "local.startup_log",
                        "insert" : {

                        },
                        "client" : "0.0.0.0:0",
                        "desc" : "initandlisten",
                        "threadId" : "0x7fb15a662b40",
                        "waitingForLock" : false,
                        "numYields" : 0,
                        "lockStats" : {
                                "timeLockedMicros" : {
                                        "R" : NumberLong(0),
                                        "W" : NumberLong(75945)
                                },
                                "timeAcquiringMicros" : {
                                        "r" : NumberLong(0),
                                        "w" : NumberLong(2)
                                }
                        }
                },
                {
                        "opid" : 0,
                        "active" : false,
    :
    :
    :
```

## ７．スクリプトを構造化する
 - utils.js 汎用ユーティリティ
 - run.js 今回の解析プログラム
 
本来は絶対パスがお勧めだがbash側でcd するなら相対でも成り立つ
### utils.js

```js
function Utils() {
}
Utils.prototype.inc = function(i) { return i + 1; }
```
### run.js

```js
var i = INPUT
var utils = new Utils();
var j = utils.inc(i);
print(j);
```
### mongo shell起動

```bash
$ mongo --quiet --eval 'INPUT=10' utils.js run.js
10
loading file: /tmp/utils.js
loading file: /tmp/run.js
11
```
## ８．loadも便利
普通にmongo shellを上げたときも手打ちでloadしてあげれば
自分用の便利な機能が使えるようになる。

### run.js

```js
load('utils.js')
var i = INPUT
var utils = new Utils();
var j = utils.inc(i);
print(j);
```
### mongo shell起動

```bash
$ mongo --quiet --eval 'INPUT=10' run.js
10
11
```

## ９．おまけ
コレクション削除スクリプト

### 使い方
test DB の mycol* のコレクション達をdropする

```js
> load('utils.js')
> utils.cleanCollection('test.mycol')
```

### utils.js

```js
var utils = {
  parseCollection : function(ns){
    var ns_split  = ns.split('\.');
    return {
      db  : ns_split.shift() ,
      col : ns_split.join('\.')
    };
  },
  _cleanCollections : function (dbname,cond){
    var collections = db.getMongo().getDB(dbname).getCollectionNames();
    var re = new RegExp(cond);
    for ( var c in collections ) {
      var name = collections[c];
      if ( name.match(re) ){
        db.getMongo().getDB(dbname).getCollection(name).drop();
      }
    }
  },
  cleanCollections : function (ns){
    var pns = utils.parseCollection(ns);
    utils._cleanCollections(pns.db,'^' + pns.col);
  }
}
```