mongo的runCommand与集合操作函数的关系

除了特殊注释外,本文的测试结果均基于 spring-data-mongodb:1.10.6.RELEASE(spring-boot-starter:1.5.6.RELEASE),MongoDB 3.0.6


 一:单纯的主从关系

  按照我们多年的mvc经验,所有的方法的调用都应该遵循一个从上到下的关系,没有遇到过dao层调service层的。

  所以主观上我们需要确认一个顺序,是runCommand封装了集合操作函数,还是集合操作函数封装了runCommand?

  这里我们进入mongo.exe,通过方法的源码来看看(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 );
}

   runComman的底层使用findOne,很完美的主从调用关系,符合了我们的代码分层审美。

二、命令&方法,蛋和鸡

  接下来我们来看一个异类: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 shell的对应关系

  四:mongo中的游标与数据一致性的取舍

   

posted @ 2018-11-12 21:40  有营养的yyl  阅读(...)  评论(...编辑  收藏