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语句
三:spring-data-mongodb与mongo shell的对应关系