diff --git a/db/db.cpp b/db/db.cpp index 7875043eda9..47d360c845c 100644 --- a/db/db.cpp +++ b/db/db.cpp @@ -152,6 +152,7 @@ void receivedQuery(MessagingPort& dbMsgPort, Message& m, stringstream& ss) { DbMessage d(m); const char *ns = d.getns(); setClient(ns); + int ntoskip = d.pullInt(); int ntoreturn = d.pullInt(); JSObj query = d.nextJsObj(); auto_ptr< set > fields; @@ -160,7 +161,7 @@ void receivedQuery(MessagingPort& dbMsgPort, Message& m, stringstream& ss) { d.nextJsObj().getFieldNames(*fields); } QueryResult* msgdata = - runQuery(ns, ntoreturn, query, fields, ss); + runQuery(ns, ntoskip, ntoreturn, query, fields, ss); Message resp; resp.setData(msgdata, true); dbMsgPort.reply(m, resp); diff --git a/db/query.cpp b/db/query.cpp index b3724a3874b..ad184f30804 100644 --- a/db/query.cpp +++ b/db/query.cpp @@ -332,9 +332,10 @@ done: return true; } -QueryResult* runQuery(const char *ns, int ntoreturn, JSObj jsobj, +QueryResult* runQuery(const char *ns, int ntoskip, int ntoreturn, JSObj jsobj, auto_ptr< set > filter, stringstream& ss) { ss << "query:" << ns << " ntoreturn:" << ntoreturn; + if( ntoskip ) ss << " ntoskip:" << ntoskip; if( jsobj.objsize() > 100 ) ss << " querysz:" << jsobj.objsize(); if( queryTraceLevel >= 1 ) @@ -380,33 +381,40 @@ QueryResult* runQuery(const char *ns, int ntoreturn, JSObj jsobj, if( c->tempStopOnMiss() ) break; } - else if( !deep || !c->dup(c->currLoc()) ) { - bool ok = true; - if( filter.get() ) { - JSObj x; - ok = x.addFields(js, *filter) > 0; - if( ok ) - b.append((void*) x.objdata(), x.objsize()); + else if( !deep || !c->dup(c->currLoc()) ) { // i.e., check for dups on deep items only + // got a match. + if( ntoskip > 0 ) { + ntoskip--; } else { - b.append((void*) js.objdata(), js.objsize()); - } - if( ok ) { - n++; - if( (ntoreturn>0 && (n >= ntoreturn || b.len() > 16*1024*1024)) || - (ntoreturn==0 && b.len()>1*1024*1024) ) { - // more...so save a cursor - ClientCursor *cc = new ClientCursor(); - cc->c = c; - cursorid = allocCursorId(); - cc->cursorid = cursorid; - cc->matcher = matcher; - cc->ns = ns; - cc->pos = n; - ClientCursor::add(cc); - cc->updateLocation(); - cc->filter = filter; - break; + bool ok = true; + if( filter.get() ) { + // we just want certain fields from the object. + JSObj x; + ok = x.addFields(js, *filter) > 0; + if( ok ) + b.append((void*) x.objdata(), x.objsize()); + } + else { + b.append((void*) js.objdata(), js.objsize()); + } + if( ok ) { + n++; + if( (ntoreturn>0 && (n >= ntoreturn || b.len() > 16*1024*1024)) || + (ntoreturn==0 && b.len()>1*1024*1024) ) { + // more...so save a cursor + ClientCursor *cc = new ClientCursor(); + cc->c = c; + cursorid = allocCursorId(); + cc->cursorid = cursorid; + cc->matcher = matcher; + cc->ns = ns; + cc->pos = n; + ClientCursor::add(cc); + cc->updateLocation(); + cc->filter = filter; + break; + } } } } diff --git a/db/query.h b/db/query.h index 8e410450f4c..8f6891b8704 100644 --- a/db/query.h +++ b/db/query.h @@ -24,6 +24,7 @@ dbQuery: int reserved; string collection; + int nToSkip; int nToReturn; // how many you want back as the beginning of the cursor data JSObject query; [JSObject fieldsToReturn] @@ -62,7 +63,7 @@ struct QueryResult : public MsgData { QueryResult* getMore(const char *ns, int ntoreturn, long long cursorid); -QueryResult* runQuery(const char *ns, int ntoreturn, +QueryResult* runQuery(const char *ns, int ntoskip, int ntoreturn, JSObj j, auto_ptr< set > fieldFilter, stringstream&);