1. 程式人生 > >mongo的runCommand與集合操作函數的關系

mongo的runCommand與集合操作函數的關系

data javascrip 什麽 script and rar 特殊 release cti

除了特殊註釋外,本文的測試結果均基於 spring-data-mongodb:1.10.6.RELEASE(spring-boot-starter:1.5.6.RELEASE),MongoDB 3.0.6


一:單純的主從關系

  按照我們多年的mvc經驗,所有的方法的調用都應該遵循一個從上到下的關系,沒有遇到過dao層調service層的。

  所以主觀上我們需要確認一個順序,是runCommand封裝了集合操作函數,還是集合操作函數封裝了runCommand?

  這裏我們通過方法的源碼來看看(js中所有的方法不加小括號時都可以直接打印出該方法的代碼)

> db.runCommand
function ( obj, extra ){ if ( typeof( obj ) == "string" ){ var n = {}; n[obj] = 1; obj = n; if ( extra && typeof( extra ) == "object" ) { for ( var x in extra ) { n[x] = extra[x]; } } } return
this.getCollection( "$cmd" ).findOne( obj ); }

  很完美的主從調用關系,符合了我們的審美。

二、命令&方法,蛋和雞

  接下來我們來看一個異類:aggregate。

> db.user.aggregate
function (pipeline, extraOpts) {
    if (!(pipeline instanceof Array)) {
        // support legacy varargs form. (Also handles db.foo.aggregate())
        pipeline = argumentsToArray(arguments)
        extraOpts 
= {} } else if (extraOpts === undefined) { extraOpts = {}; } var cmd = {pipeline: pipeline}; Object.extend(cmd, extraOpts); if (!(‘cursor‘ in cmd)) { // implicitly use cursors cmd.cursor = {}; } var res = this.runCommand("aggregate", cmd); //...此處省去了一些無關代碼,可自行下載3.0.06版本的mongo查看 return res; }

  這個runCommand不會就是那個runCommand吧?,讓我們將this替換為方法的調用對象db.user。(關於js中this指代的對象建議閱讀王福朋的深入理解javascript的原型和閉包)

> db.user.runCommand
function ( cmd , params ){
    if ( typeof( cmd ) == "object" )
        return this._db._dbCommand( cmd );

    var c = {};
    c[cmd] = this.getName();
    if ( params )
        Object.extend( c , params );
    return this._db._dbCommand( c );
}

  讓我們再替換掉this,繼續往下看。

> db.user._db._dbCommand
function ( obj, extra ){
    if ( typeof( obj ) == "string" ){
        var n = {};
        n[obj] = 1;
        obj = n;
        if ( extra && typeof( extra ) == "object" ) {
            for ( var x in extra ) {
                n[x] = extra[x];
            }
        }
    }
    return this.getCollection( "$cmd" ).findOne( obj );
}

  db._collection_.aggregate()繞了一大圈,又回到了db.$cmd.findOne()。為什麽不讓aggregate直接調用findOne,再讓db.runCommand{{"aggregate":"_collection_","pipeline":[]}}調用db._collection_.aggregate?這種雞生蛋,蛋生雞的結構,後期又該如何快速的進行版本升級?這樣做的原因我們在第四章 MONGO中的特殊集合$CMD 中會講。現在我們先記住aggregate的這種調用模式,然後研究在spring-data-mongodb中,該從哪一層入手使用原生的aggregate查詢。


  一:spring-data-mongodb 使用原生aggregate語句

  二:mongo的runCommand與集合操作函數的關系

  三:spring-data-mongodb底層與mongo-driver的交互

  四:mongo中的特殊集合$cmd

  

mongo的runCommand與集合操作函數的關系