在之前的2篇文章中分别分析了mongod和mongo的启动流程,下面开始将分析mongodb的查询,由于查询部分流程比较长,将分成mongo端的请求,mongod端的数据库的加载,mongod query的选取,mongod文档的匹配与数据的响应几部分来分析。
首先进入mongo的查询请求部分.mongo的查询请求部分归纳起来很简单就是将请求分装成一个Message结构,然后将其发送到服务端,等待服务端的相应数据,取得数据最后显示结果.下面来看具体流程分析吧.
当我们点击db.coll.find({x:1})时按照上一篇文章的讲解,我们首先来到了mongo/shell/dbshell.cpp
if ( ! wascmd ) {
try {
if ( scope->exec( code.c_str() , "(shell)" , false , true , false ) )//执行相应的javascript代码
scope->exec( "shellPrintHelper( __lastres__ );" , "(shell2)" , true , true , false );
}
catch ( std::exception& e ) {
cout << "error:" << e.what() << endl;
}
}
下面进入javascript代码,其在mongo/shell/collection.js.
//这里因为我们只设置了query,所以其它选项都是空的,this.getQueryOptions()目前只有一个SlaveOK的option,在replset模式下是不能查询secondary服务器的,需要调用rs.SlaveOK()之后才能对secondary进行查询,其执行SlaveOK后每次查询时都会添加一个QueryOption.
DBCollection.prototype.find = function (query, fields, limit, skip, batchSize, options) {
return new DBQuery( this._mongo , this._db , this ,
this._fullName , this._massageObject( query ) , fields , limit , skip , batchSize , options || this.getQueryOptions() );
}
继续前进看看DBQuery,上一篇文章提到这里的new DBQuery对象的创建发生在:
JSBool dbquery_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ) {
try {
smuassert( cx , "DDQuery needs at least 4 args" , argc >= 4 );
//整个代码都是创建一个DBQuery对象,并未进行任何的查询请求动作
Convertor c(cx);
c.setProperty( obj , "_mongo" , argv[0] );
c.setProperty( obj , "_db" , argv[1] );
c.setProperty( obj , "_collection" , argv[2] );
c.setProperty( obj , "_ns" , argv[3] );
if ( argc > 4 && JSVAL_IS_OBJECT( argv[4] ) )
c.setProperty( obj , "_query" , argv[4] );
else {
JSObject * temp = JS_NewObject( cx , 0 , 0 , 0 );
CHECKNEWOBJECT( temp, cx, "dbquery_constructor" );
c.setProperty( obj , "_query" , OBJECT_TO_JSVAL( temp ) );
}
if ( argc > 5 && JSVAL_IS_OBJECT( argv[5] ) )
c.setProperty( obj , "_fields" , argv[5] );
else
c.setProperty( obj , "_fields" , JSVAL_NULL );
if ( argc > 6 && JSVAL_IS_NUMBER( argv[6] ) )
c.setProperty( obj , "_limit" , argv[6] );
else
c.setProperty( obj , "_limit" , JSVAL_ZERO );
if ( argc > 7 && JSVAL_IS_NUMBER( argv[7] ) )
c.setProperty( obj , "_skip" , argv[7] );
else
c.setProperty( obj , "_skip" , JSVAL_ZERO );
if ( argc > 8 && JSVAL_IS_NUMBER( argv[8] ) )
c.setProperty( obj , "_batchSize" , argv[8] );
else
c.setProperty( obj , "_batchSize" , JSVAL_ZERO );
if ( argc > 9 && JSVAL_IS_NUMBER( argv[9] ) )
c.setProperty( obj , "_options" , argv[9] );
else
c.setProperty( obj , "_options" , JSVAL_ZERO );
c.