本文整理汇总了C++中BSONElement类的典型用法代码示例。如果您正苦于以下问题:C++ BSONElement类的具体用法?C++ BSONElement怎么用?C++ BSONElement使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了BSONElement类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: newRunQuery
//.........这里部分代码省略.........
ClientCursor::registerRunner(runner.get());
runner->setYieldPolicy(Runner::YIELD_AUTO);
auto_ptr<DeregisterEvenIfUnderlyingCodeThrows> safety(
new DeregisterEvenIfUnderlyingCodeThrows(runner.get()));
BSONObj obj;
Runner::RunnerState state;
// set this outside loop. we will need to use this both within loop and when deciding
// to fill in explain information
const bool isExplain = pq.isExplain();
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
// If we're sharded make sure that we don't return any data that hasn't been migrated
// off of our shared yet.
if (collMetadata) {
// This information can change if we yield and as such we must make sure to re-fetch
// it if we yield.
KeyPattern kp(collMetadata->getKeyPattern());
// This performs excessive BSONObj creation but that's OK for now.
if (!collMetadata->keyBelongsToMe(kp.extractSingleKey(obj))) { continue; }
}
// Add result to output buffer. This is unnecessary if explain info is requested
if (!isExplain) {
bb.appendBuf((void*)obj.objdata(), obj.objsize());
}
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (pq.hasOption(QueryOption_OplogReplay)) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
// TODO: only one type of 2d search doesn't support this. We need a way to pull it out
// of CanonicalQuery. :(
const bool supportsGetMore = true;
if (isExplain) {
if (enoughForExplain(pq, numResults)) {
break;
}
}
else if (!supportsGetMore && (enough(pq, numResults)
|| bb.len() >= MaxBytesToReturnToClientAtOnce)) {
break;
}
else if (enoughForFirstBatch(pq, numResults, bb.len())) {
// If only one result requested assume it's a findOne() and don't save the cursor.
if (pq.wantMore() && 1 != pq.getNumToReturn()) {
saveClientCursor = true;
}
break;
}
}
// If we cache the runner later, we want to deregister it as it receives notifications
// anyway by virtue of being cached.
//
// If we don't cache the runner later, we are deleting it, so it must be deregistered.
//
// So, no matter what, deregister the runner.
示例2: run
bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
Timer t;
string ns = dbname + '.' + cmdObj.firstElement().valuestr();
string key = cmdObj["key"].valuestrsafe();
BSONObj keyPattern = BSON( key << 1 );
BSONObj query = getQuery( cmdObj );
int bufSize = BSONObjMaxUserSize - 4096;
BufBuilder bb( bufSize );
char * start = bb.buf();
BSONArrayBuilder arr( bb );
BSONElementSet values;
long long nscanned = 0; // locations looked at
long long nscannedObjects = 0; // full objects looked at
long long n = 0; // matches
MatchDetails md;
NamespaceDetails * d = nsdetails( ns.c_str() );
if ( ! d ) {
result.appendArray( "values" , BSONObj() );
result.append( "stats" , BSON( "n" << 0 << "nscanned" << 0 << "nscannedObjects" << 0 ) );
return true;
}
shared_ptr<Cursor> cursor;
if ( ! query.isEmpty() ) {
cursor = NamespaceDetailsTransient::getCursor(ns.c_str() , query , BSONObj() );
}
else {
// query is empty, so lets see if we can find an index
// with the key so we don't have to hit the raw data
NamespaceDetails::IndexIterator ii = d->ii();
while ( ii.more() ) {
IndexDetails& idx = ii.next();
if ( d->isMultikey( ii.pos() - 1 ) )
continue;
if ( idx.inKeyPattern( key ) ) {
cursor = NamespaceDetailsTransient::bestGuessCursor( ns.c_str() ,
BSONObj() ,
idx.keyPattern() );
if( cursor.get() ) break;
}
}
if ( ! cursor.get() )
cursor = NamespaceDetailsTransient::getCursor(ns.c_str() , query , BSONObj() );
}
verify( cursor );
string cursorName = cursor->toString();
auto_ptr<ClientCursor> cc (new ClientCursor(QueryOption_NoCursorTimeout, cursor, ns));
while ( cursor->ok() ) {
nscanned++;
bool loadedRecord = false;
if ( cursor->currentMatches( &md ) && !cursor->getsetdup( cursor->currLoc() ) ) {
n++;
BSONObj holder;
BSONElementSet temp;
loadedRecord = ! cc->getFieldsDotted( key , temp, holder );
for ( BSONElementSet::iterator i=temp.begin(); i!=temp.end(); ++i ) {
BSONElement e = *i;
if ( values.count( e ) )
continue;
int now = bb.len();
uassert(10044, "distinct too big, 16mb cap", ( now + e.size() + 1024 ) < bufSize );
arr.append( e );
BSONElement x( start + now );
values.insert( x );
}
}
if ( loadedRecord || md.hasLoadedRecord() )
nscannedObjects++;
cursor->advance();
if (!cc->yieldSometimes( ClientCursor::MaybeCovered )) {
cc.release();
break;
}
//.........这里部分代码省略.........
示例3: csvString
// Gets the string representation of a BSON object that can be correctly written to a CSV file
string csvString (const BSONElement& object) {
const char* binData; // Only used with BinData type
switch (object.type()) {
case MinKey:
return "$MinKey";
case MaxKey:
return "$MaxKey";
case NumberInt:
case NumberDouble:
case NumberLong:
case Bool:
return object.toString(false);
case String:
case Symbol:
return csvEscape(object.toString(false), true);
case Object:
return csvEscape(object.jsonString(Strict, false));
case Array:
return csvEscape(object.jsonString(Strict, false));
case BinData:
int len;
binData = object.binDataClean(len);
return toHex(binData, len);
case jstOID:
return "ObjectID(" + object.OID().toString() + ")"; // OIDs are always 24 bytes
case Date:
return timeToISOString(object.Date() / 1000);
case Timestamp:
return csvEscape(object.jsonString(Strict, false));
case RegEx:
return csvEscape("/" + string(object.regex()) + "/" + string(object.regexFlags()));
case Code:
return csvEscape(object.toString(false));
case CodeWScope:
if (string(object.codeWScopeScopeData()) == "") {
return csvEscape(object.toString(false));
} else {
return csvEscape(object.jsonString(Strict, false));
}
case EOO:
case Undefined:
case DBRef:
case jstNULL:
cerr << "Invalid BSON object type for CSV output: " << object.type() << endl;
return "";
}
// Can never get here
verify(false);
return "";
}
示例4: debug
bool debug( const BSONObj& o , int depth=0) {
string prefix = "";
for ( int i=0; i<depth; i++ ) {
prefix += "\t\t\t";
}
int read = 4;
try {
cout << prefix << "--- new object ---\n";
cout << prefix << "\t size : " << o.objsize() << "\n";
BSONObjIterator i(o);
while ( i.more() ) {
BSONElement e = i.next();
cout << prefix << "\t\t " << e.fieldName() << "\n" << prefix << "\t\t\t type:" << setw(3) << e.type() << " size: " << e.size() << endl;
if ( ( read + e.size() ) > o.objsize() ) {
cout << prefix << " SIZE DOES NOT WORK" << endl;
return false;
}
read += e.size();
try {
e.validate();
if ( e.isABSONObj() ) {
if ( ! debug( e.Obj() , depth + 1 ) ) {
//return false;
cout << prefix << "\t\t\t BAD BAD BAD" << endl;
if ( e.size() < 1000 ) {
cout << "---\n" << e.Obj().hexDump() << "\n---" << endl;
}
}
}
else if ( e.type() == String && ! isValidUTF8( e.valuestr() ) ) {
cout << prefix << "\t\t\t" << "bad utf8 String!" << endl;
}
else if ( logLevel > 0 ) {
cout << prefix << "\t\t\t" << e << endl;
}
}
catch ( std::exception& e ) {
cout << prefix << "\t\t\t bad value: " << e.what() << endl;
}
}
}
catch ( std::exception& e ) {
cout << prefix << "\tbad\t" << e.what() << endl;
cout << "----\n" << o.hexDump() << "\n---" << endl;
}
return true;
}
示例5: uassert
/**
* actually applies a reduce, to a list of tuples (key, value).
* After the call, tuples will hold a single tuple {"0": key, "1": value}
*/
void JSReducer::_reduce( const BSONList& tuples , BSONObj& key , int& endSizeEstimate ) {
uassert( 10074 , "need values" , tuples.size() );
int sizeEstimate = ( tuples.size() * tuples.begin()->getField( "value" ).size() ) + 128;
// need to build the reduce args: ( key, [values] )
BSONObjBuilder reduceArgs( sizeEstimate );
boost::scoped_ptr<BSONArrayBuilder> valueBuilder;
int sizeSoFar = 0;
unsigned n = 0;
for ( ; n<tuples.size(); n++ ) {
BSONObjIterator j(tuples[n]);
BSONElement keyE = j.next();
if ( n == 0 ) {
reduceArgs.append( keyE );
key = keyE.wrap();
sizeSoFar = 5 + keyE.size();
valueBuilder.reset(new BSONArrayBuilder( reduceArgs.subarrayStart( "tuples" ) ));
}
BSONElement ee = j.next();
uassert( 13070 , "value too large to reduce" , ee.size() < ( BSONObjMaxUserSize / 2 ) );
if ( sizeSoFar + ee.size() > BSONObjMaxUserSize ) {
assert( n > 1 ); // if not, inf. loop
break;
}
valueBuilder->append( ee );
sizeSoFar += ee.size();
}
assert(valueBuilder);
valueBuilder->done();
BSONObj args = reduceArgs.obj();
Scope * s = _func.scope();
s->invokeSafe( _func.func() , &args, 0 );
++numReduces;
if ( s->type( "return" ) == Array ) {
uasserted( 10075 , "reduce -> multiple not supported yet");
return;
}
endSizeEstimate = key.objsize() + ( args.objsize() / tuples.size() );
if ( n == tuples.size() )
return;
// the input list was too large, add the rest of elmts to new tuples and reduce again
// note: would be better to use loop instead of recursion to avoid stack overflow
BSONList x;
for ( ; n < tuples.size(); n++ ) {
x.push_back( tuples[n] );
}
BSONObjBuilder temp( endSizeEstimate );
temp.append( key.firstElement() );
s->append( temp , "1" , "return" );
x.push_back( temp.obj() );
_reduce( x , key , endSizeEstimate );
}
示例6: oi
// static
void ExpressionKeysPrivate::get2DKeys(const BSONObj &obj,
const TwoDIndexingParams& params,
BSONObjSet* keys,
std::vector<BSONObj>* locs) {
BSONElementMSet bSet;
// Get all the nested location fields, but don't return individual elements from
// the last array, if it exists.
obj.getFieldsDotted(params.geo.c_str(), bSet, false);
if (bSet.empty())
return;
for (BSONElementMSet::iterator setI = bSet.begin(); setI != bSet.end(); ++setI) {
BSONElement geo = *setI;
if (geo.eoo() || !geo.isABSONObj())
continue;
//
// Grammar for location lookup:
// locs ::= [loc,loc,...,loc]|{<k>:loc,<k>:loc,...,<k>:loc}|loc
// loc ::= { <k1> : #, <k2> : # }|[#, #]|{}
//
// Empty locations are ignored, preserving single-location semantics
//
BSONObj embed = geo.embeddedObject();
if (embed.isEmpty())
continue;
// Differentiate between location arrays and locations
// by seeing if the first element value is a number
bool singleElement = embed.firstElement().isNumber();
BSONObjIterator oi(embed);
while (oi.more()) {
BSONObj locObj;
if (singleElement) {
locObj = embed;
} else {
BSONElement locElement = oi.next();
uassert(16804, mongoutils::str::stream() <<
"location object expected, location array not in correct format",
locElement.isABSONObj());
locObj = locElement.embeddedObject();
if(locObj.isEmpty())
continue;
}
BSONObjBuilder b(64);
// Remember the actual location object if needed
if (locs)
locs->push_back(locObj);
// Stop if we don't need to get anything but location objects
if (!keys) {
if (singleElement) break;
else continue;
}
params.geoHashConverter->hash(locObj, &obj).appendHashMin(&b, "");
// Go through all the other index keys
for (vector<pair<string, int> >::const_iterator i = params.other.begin();
i != params.other.end(); ++i) {
// Get *all* fields for the index key
BSONElementSet eSet;
obj.getFieldsDotted(i->first, eSet);
if (eSet.size() == 0)
b.appendNull("");
else if (eSet.size() == 1)
b.appendAs(*(eSet.begin()), "");
else {
// If we have more than one key, store as an array of the objects
BSONArrayBuilder aBuilder;
for (BSONElementSet::iterator ei = eSet.begin(); ei != eSet.end();
++ei) {
aBuilder.append(*ei);
}
b.append("", aBuilder.arr());
}
}
keys->insert(b.obj());
if(singleElement) break;
}
}
}
示例7: handleRESTQuery
void handleRESTQuery( string ns , string action , BSONObj & params , int & responseCode , stringstream & out ) {
Timer t;
int skip = _getOption( params["skip"] , 0 );
int num = _getOption( params["limit"] , _getOption( params["count" ] , 1000 ) ); // count is old, limit is new
int one = 0;
if ( params["one"].type() == String && tolower( params["one"].valuestr()[0] ) == 't' ) {
num = 1;
one = 1;
}
BSONObjBuilder queryBuilder;
BSONObjIterator i(params);
while ( i.more() ){
BSONElement e = i.next();
string name = e.fieldName();
if ( ! name.find( "filter_" ) == 0 )
continue;
const char * field = name.substr( 7 ).c_str();
const char * val = e.valuestr();
char * temp;
// TODO: this is how i guess if something is a number. pretty lame right now
double number = strtod( val , &temp );
if ( temp != val )
queryBuilder.append( field , number );
else
queryBuilder.append( field , val );
}
BSONObj query = queryBuilder.obj();
auto_ptr<DBClientCursor> cursor = db.query( ns.c_str() , query, num , skip );
if ( one ) {
if ( cursor->more() ) {
BSONObj obj = cursor->next();
out << obj.jsonString() << "\n";
}
else {
responseCode = 404;
}
return;
}
out << "{\n";
out << " \"offset\" : " << skip << ",\n";
out << " \"rows\": [\n";
int howMany = 0;
while ( cursor->more() ) {
if ( howMany++ )
out << " ,\n";
BSONObj obj = cursor->next();
out << " " << obj.jsonString();
}
out << "\n ],\n\n";
out << " \"total_rows\" : " << howMany << " ,\n";
out << " \"query\" : " << query.jsonString() << " ,\n";
out << " \"millis\" : " << t.millis() << "\n";
out << "}\n";
}
示例8: init
Status RegexMatchExpression::init( const StringData& path, const BSONElement& e ) {
if ( e.type() != RegEx )
return Status( ErrorCodes::BadValue, "regex not a regex" );
return init( path, e.regex(), e.regexFlags() );
}
示例9: matchesSingleElement
bool ModMatchExpression::matchesSingleElement( const BSONElement& e ) const {
if ( !e.isNumber() )
return false;
return e.numberLong() % _divisor == _remainder;
}
示例10: typeIt
bool GeoParser::parseCap(const BSONObj& obj, CapWithCRS *out) {
if (isLegacyCenter(obj)) {
BSONObjIterator typeIt(obj);
BSONElement type = typeIt.next();
BSONObjIterator objIt(type.embeddedObject());
BSONElement center = objIt.next();
if (!parseLegacyPoint(center.Obj(), &out->circle.center)) { return false; }
BSONElement radius = objIt.next();
out->circle.radius = radius.number();
out->crs = FLAT;
} else {
BSONObjIterator typeIt(obj);
BSONElement type = typeIt.next();
BSONObjIterator objIt(type.embeddedObject());
BSONObj centerObj = objIt.next().Obj();
S2Point centerPoint;
BSONObjIterator it(centerObj);
BSONElement x = it.next();
BSONElement y = it.next();
centerPoint = coordToPoint(x.Number(), y.Number());
BSONElement radiusElt = objIt.next();
double radius = radiusElt.number();
out->cap = S2Cap::FromAxisAngle(centerPoint, S1Angle::Radians(radius));
out->crs = SPHERE;
}
return true;
}
示例11: fixDocumentForInsert
StatusWith<BSONObj> fixDocumentForInsert( const BSONObj& doc ) {
if ( doc.objsize() > BSONObjMaxUserSize )
return StatusWith<BSONObj>( ErrorCodes::BadValue,
str::stream()
<< "object to insert too large"
<< doc.objsize() );
bool firstElementIsId = doc.firstElement().fieldNameStringData() == "_id";
bool hasTimestampToFix = false;
{
BSONObjIterator i( doc );
while ( i.more() ) {
BSONElement e = i.next();
if ( e.type() == Timestamp && e.timestampValue() == 0 ) {
// we replace Timestamp(0,0) at the top level with a correct value
// in the fast pass, we just mark that we want to swap
hasTimestampToFix = true;
break;
}
const char* fieldName = e.fieldName();
if ( fieldName[0] == '$' ) {
return StatusWith<BSONObj>( ErrorCodes::BadValue,
str::stream()
<< "Document can't have $ prefixed field names: "
<< e.fieldName() );
}
// check no regexp for _id (SERVER-9502)
// also, disallow undefined and arrays
if ( str::equals( fieldName, "_id") ) {
if ( e.type() == RegEx ) {
return StatusWith<BSONObj>( ErrorCodes::BadValue,
"can't use a regex for _id" );
}
if ( e.type() == Undefined ) {
return StatusWith<BSONObj>( ErrorCodes::BadValue,
"can't use a undefined for _id" );
}
if ( e.type() == Array ) {
return StatusWith<BSONObj>( ErrorCodes::BadValue,
"can't use an array for _id" );
}
if ( e.type() == Object ) {
BSONObj o = e.Obj();
Status s = o.storageValidEmbedded();
if ( !s.isOK() )
return StatusWith<BSONObj>( s );
}
}
}
}
if ( firstElementIsId && !hasTimestampToFix )
return StatusWith<BSONObj>( BSONObj() );
bool hadId = firstElementIsId;
BSONObjIterator i( doc );
BSONObjBuilder b( doc.objsize() + 16 );
if ( firstElementIsId ) {
b.append( doc.firstElement() );
i.next();
}
else {
BSONElement e = doc["_id"];
if ( e.type() ) {
b.append( e );
hadId = true;
}
else {
b.appendOID( "_id", NULL, true );
}
}
while ( i.more() ) {
BSONElement e = i.next();
if ( hadId && e.fieldNameStringData() == "_id" ) {
// no-op
}
else if ( e.type() == Timestamp && e.timestampValue() == 0 ) {
mutex::scoped_lock lk(OpTime::m);
b.append( e.fieldName(), OpTime::now(lk) );
}
else {
b.append( e );
}
}
return StatusWith<BSONObj>( b.obj() );
}
示例12: run
bool run(const string& dbname, BSONObj& cmdObj, int,
string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string ns = dbname + "." + cmdObj.firstElement().valuestr();
NamespaceDetails *nsd = nsdetails(ns);
if (NULL == nsd) {
errmsg = "can't find ns";
return false;
}
vector<int> idxs;
nsd->findIndexByType(GEOSEARCHNAME, idxs);
if (idxs.size() == 0) {
errmsg = "no geoSearch index";
return false;
}
if (idxs.size() > 1) {
errmsg = "more than 1 geosearch index";
return false;
}
BSONElement nearElt = cmdObj["near"];
BSONElement maxDistance = cmdObj["maxDistance"];
BSONElement search = cmdObj["search"];
uassert(13318, "near needs to be an array", nearElt.isABSONObj());
uassert(13319, "maxDistance needs a number", maxDistance.isNumber());
uassert(13320, "search needs to be an object", search.type() == Object);
unsigned limit = 50;
if (cmdObj["limit"].isNumber())
limit = static_cast<unsigned>(cmdObj["limit"].numberInt());
int idxNum = idxs[0];
IndexDetails& id = nsd->idx(idxNum);
if (CatalogHack::testIndexMigration()) {
auto_ptr<IndexDescriptor> desc(CatalogHack::getDescriptor(nsd, idxNum));
auto_ptr<HaystackAccessMethod> ham(new HaystackAccessMethod(desc.get()));
ham->searchCommand(nearElt.Obj(), maxDistance.numberDouble(), search.Obj(),
&result, limit);
} else {
GeoHaystackSearchIndex *si =
static_cast<GeoHaystackSearchIndex*>(id.getSpec().getType());
verify(&id == si->getDetails());
si->searchCommand(nsd, nearElt.Obj(), maxDistance.numberDouble(), search.Obj(),
result, limit);
}
return 1;
}
示例13: hash
// TODO(hk): consider moving hash/unhash/makeString out
int hash(const BSONElement& e) const {
uassert(13322, "geo field is not a number", e.isNumber());
return hash(e.numberDouble());
}
示例14: searchCommand
void searchCommand(NamespaceDetails* nsd,
const BSONObj& n /*near*/, double maxDistance, const BSONObj& search,
BSONObjBuilder& result, unsigned limit) {
Timer t;
LOG(1) << "SEARCH near:" << n << " maxDistance:" << maxDistance
<< " search: " << search << endl;
int x, y;
{
BSONObjIterator i(n);
x = hash(i.next());
y = hash(i.next());
}
int scale = static_cast<int>(ceil(maxDistance / _bucketSize));
GeoHaystackSearchHopper hopper(n, maxDistance, limit, _geoField);
long long btreeMatches = 0;
// TODO(hk): Consider starting with a (or b)=0, then going to a=+-1, then a=+-2, etc.
// Would want a HaystackKeyIterator or similar for this, but it'd be a nice
// encapsulation allowing us to S2-ify this trivially/abstract the key details.
for (int a = -scale; a <= scale && !hopper.limitReached(); ++a) {
for (int b = -scale; b <= scale && !hopper.limitReached(); ++b) {
BSONObjBuilder bb;
bb.append("", makeString(x + a, y + b));
for (unsigned i = 0; i < _otherFields.size(); i++) {
// See if the non-geo field we're indexing on is in the provided search term.
BSONElement e = search.getFieldDotted(_otherFields[i]);
if (e.eoo())
bb.appendNull("");
else
bb.appendAs(e, "");
}
BSONObj key = bb.obj();
GEOQUADDEBUG("KEY: " << key);
// TODO(hk): this keeps a set of all DiskLoc seen in this pass so that we don't
// consider the element twice. Do we want to instead store a hash of the set?
// Is this often big?
set<DiskLoc> thisPass;
// Lookup from key to key, inclusive.
scoped_ptr<BtreeCursor> cursor(BtreeCursor::make(nsd,
*getDetails(),
key,
key,
true,
1));
while (cursor->ok() && !hopper.limitReached()) {
pair<set<DiskLoc>::iterator, bool> p = thisPass.insert(cursor->currLoc());
// If a new element was inserted (haven't seen the DiskLoc before), p.second
// is true.
if (p.second) {
hopper.consider(cursor->currLoc());
GEOQUADDEBUG("\t" << cursor->current());
btreeMatches++;
}
cursor->advance();
}
}
}
BSONArrayBuilder arr(result.subarrayStart("results"));
int num = hopper.appendResultsTo(&arr);
arr.done();
{
BSONObjBuilder b(result.subobjStart("stats"));
b.append("time", t.millis());
b.appendNumber("btreeMatches", btreeMatches);
b.append("n", num);
b.done();
}
}
示例15: parseQuery
PlanStage* parseQuery(OperationContext* txn,
Collection* collection,
BSONObj obj,
WorkingSet* workingSet,
OwnedPointerVector<MatchExpression>* exprs) {
BSONElement firstElt = obj.firstElement();
if (!firstElt.isABSONObj()) {
return NULL;
}
BSONObj paramObj = firstElt.Obj();
MatchExpression* matcher = NULL;
BSONObj nodeArgs;
// Every node has these two fields.
const string filterTag = "filter";
const string argsTag = "args";
BSONObjIterator it(paramObj);
while (it.more()) {
BSONElement e = it.next();
if (!e.isABSONObj()) {
return NULL;
}
BSONObj argObj = e.Obj();
if (filterTag == e.fieldName()) {
StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
argObj, ExtensionsCallbackReal(txn, &collection->ns()));
if (!statusWithMatcher.isOK()) {
return NULL;
}
std::unique_ptr<MatchExpression> me = std::move(statusWithMatcher.getValue());
// exprs is what will wind up deleting this.
matcher = me.release();
verify(NULL != matcher);
exprs->mutableVector().push_back(matcher);
} else if (argsTag == e.fieldName()) {
nodeArgs = argObj;
} else {
uasserted(16910,
"Unknown fieldname " + string(e.fieldName()) + " in query node " +
obj.toString());
return NULL;
}
}
string nodeName = firstElt.fieldName();
if ("ixscan" == nodeName) {
// This'll throw if it's not an obj but that's OK.
BSONObj keyPatternObj = nodeArgs["keyPattern"].Obj();
IndexDescriptor* desc =
collection->getIndexCatalog()->findIndexByKeyPattern(txn, keyPatternObj);
uassert(16890, "Can't find index: " + keyPatternObj.toString(), desc);
IndexScanParams params;
params.descriptor = desc;
params.bounds.isSimpleRange = true;
params.bounds.startKey = stripFieldNames(nodeArgs["startKey"].Obj());
params.bounds.endKey = stripFieldNames(nodeArgs["endKey"].Obj());
params.bounds.endKeyInclusive = nodeArgs["endKeyInclusive"].Bool();
params.direction = nodeArgs["direction"].numberInt();
return new IndexScan(txn, params, workingSet, matcher);
} else if ("andHash" == nodeName) {
uassert(
16921, "Nodes argument must be provided to AND", nodeArgs["nodes"].isABSONObj());
auto andStage = make_unique<AndHashStage>(txn, workingSet, collection);
int nodesAdded = 0;
BSONObjIterator it(nodeArgs["nodes"].Obj());
while (it.more()) {
BSONElement e = it.next();
uassert(16922, "node of AND isn't an obj?: " + e.toString(), e.isABSONObj());
PlanStage* subNode = parseQuery(txn, collection, e.Obj(), workingSet, exprs);
uassert(
16923, "Can't parse sub-node of AND: " + e.Obj().toString(), NULL != subNode);
// takes ownership
andStage->addChild(subNode);
++nodesAdded;
}
uassert(16927, "AND requires more than one child", nodesAdded >= 2);
return andStage.release();
} else if ("andSorted" == nodeName) {
uassert(
16924, "Nodes argument must be provided to AND", nodeArgs["nodes"].isABSONObj());
auto andStage = make_unique<AndSortedStage>(txn, workingSet, collection);
int nodesAdded = 0;
BSONObjIterator it(nodeArgs["nodes"].Obj());
while (it.more()) {
BSONElement e = it.next();
uassert(16925, "node of AND isn't an obj?: " + e.toString(), e.isABSONObj());
//.........这里部分代码省略.........