Mongodb原始碼分析 查詢結果集封裝

2021-07-27 23:59:22 字數 3130 閱讀 3183

在這個系列的開頭幾篇文章中,曾經介紹了mongodb的查詢流程,因為篇幅所限,並未介紹對cursor進行遍歷查詢時,如何將查詢記錄裝填進結果集中。

今天就針對諸如

select top n

這類返回一定數量記錄的查詢操作,來分析mongodb是如何將查詢結果裝填到結果集中的。這裡要說明的是

之前文章中的大部分程式流程,在select top 這類操作也都是要執行的,所以這裡接著之前文章所說的內容,繼續向底層挖掘相應的功能邏輯。

之前查詢流程中介紹過queryplanset::runner::run()方法,它本身為struct型別,主要是用於對執行步驟進行封裝(形成依次執行的操作流),如下(詳情見注釋):     

queryoptimizer.cpp

shared_ptr

<

queryop 

>

queryplanset::runner::run() 

//將查詢操作集合轉換成查詢佇列

std::priority_queue

<

opholder 

>

queue;

for( vector

<

shared_ptr

<

queryop 

>

>

::iterator i 

=ops.begin(); i 

!=ops.end(); 

++i ) 

}while( !

queue.empty() ) 

return

holder._op;}if

( op.error() ) 

queue.push( holder );

//如未執行完成,再次該查詢操作入隊(尾)

//使用查詢計畫?

if( 

!_plans._bestguessonly 

&&_plans._usingprerecordedplan 

&&op.nscanned() 

>

_plans._oldnscanned *10

&&_plans._special.empty() ) 

_plans._mayrecordplan 

=true

;_plans._usingprerecordedplan 

=false;}

}return

ops[ 0];

}void

queryplanset::runner::nextop( queryop 

&op )  );}

因為userqueryop是queryop的子類,如下圖:

因為本文是userqueryop物件,則上面**段中的nextop()會最終呼叫該物件的next方法:

query.cpp

virtual

void

next() 

bool

maycreatecursor1 

=_pq.wantmore() &&!

_inmemsort 

&&_pq.getnumtoreturn() !=1

&&usecursors;

if( 0) 

//判斷是否超出掃瞄項限制,形如:db.foo.find()._addspecial( "$maxscan" , 50 )

if( _pq.getmaxscan() 

&&_nscanned 

>=

_pq.getmaxscan() ) 

_nscanned =_c

->

nscanned();

if( 

!matcher()

->

matches(_c

->

currkey(), _c

->

currloc() , 

&_details ) ) 

else

else

if( _c

->

getsetdup(cl) ) 

else

else

if( _ntoskip 

>0) 

else

}else

else

if( _keyfieldsonly ) 

else

//將當前記錄填充到_buf中,以便finish方法使用該物件

fillqueryresultfromobj( _buf , _pq.getfields() , js , (_pq.showdiskloc() ?&

cl : 

0));}_n

++;if( !_c

->

supportgetmore() ) }//

判斷是否已夠返回一批資料

else

if( _pq.enoughforfirstbatch( n() , _buf.len() ) ) }//

查詢結束,繫結查詢結果資料到response

finish( 

true

);return;}

}}}}

//將游標指向下一條記錄,該方法參見

//_c

->

advance();}

上面**是實現了對相應cursor的遍歷查詢,找出(matches)合適的資料,並最後將結果新增到_buf物件中,之後再使用finish方法將_buf繫結到response中(向client傳送資訊),如下:

query.cpp

//this plan won, so set data for response broadly

void

finish( 

bool

stop ) 

//當使用scanandorder(位於scanandorder.h),表示索引不能用於排序(sort)

else

if( _inmemsort ) 

if( _c.

get() ) 

if( _pq.i***plain() ) 

else}if

( stop ) 

else}

好了,今天的內容到這裡就告一段落了,最後用一張時序圖來總結一下查詢(select top)在mongodb中的執行流程:

Mongodb原始碼分析

在之前的一篇文章中,介紹了mongos的啟動流程,在那篇文章的結尾,介紹了mongos使用balancer來進行均衡,今天就繼續講其實現方式。可以看到balancer類裡包含乙個balancerpolicy,其指向乙個均衡策略,該策略會實現查詢並收集要遷移的chunk。這裡先看一下balancer的...

MyBatis查詢的原始碼分析

如下為mybatis的乙個集合查詢 string resource mybatis.cfg.xml reader reader resources.getresourceasreader resource sqlsessionfactory ssf new sqlsessionfactorybuil...

Solr查詢過程原始碼分析

searchhandler.handlerequestbody solr搜尋主流程 1.呼叫 requesthandlerbase handlerequest req,rsp 2.原始碼分析 prepare 前期的請求引數準備工作,querycomponent可以在schemal檔案中設定,易擴充套...