// finds the names of the document with the most fields in a collection std::set<string> getCollFields(DBClientConnection& c, string db, string collection){ int longest; // mongo fieldnames = sql column names set<string> fieldnames; // get the list of ODBC supported fields (columns) from collection.meta collection // collection.meta should only contain one document std::auto_ptr<mongo::DBClientCursor> cursor = c.query(db+"."+collection+".meta"); BSONObj d = cursor->next(); if (d.nFields() != 0){ longest = d.nFields(); d.getFieldNames(fieldnames); } // if no meta collection find collection with most fields if (longest == 0) { cursor = c.query(db+"."+collection); while( cursor->more() ) { // get next doc/row/tuple BSONObj doc = cursor->next(); if(longest < doc.nFields()){ longest = doc.nFields(); doc.getFieldNames(fieldnames); } } } return fieldnames; }
int run(){ path root( getParam( "out" , "dump" ) ); string db = _db; if ( db == "*" ){ cout << "all dbs" << endl; BSONObj res = _conn.findOne( "admin.$cmd" , BSON( "listDatabases" << 1 ) ); BSONObj dbs = res.getField( "databases" ).embeddedObjectUserCheck(); set<string> keys; dbs.getFieldNames( keys ); for ( set<string>::iterator i = keys.begin() ; i != keys.end() ; i++ ) { string key = *i; BSONObj dbobj = dbs.getField( key ).embeddedObjectUserCheck(); const char * dbName = dbobj.getField( "name" ).valuestr(); if ( (string)dbName == "local" ) continue; go ( dbName , root / dbName ); } } else { go( db , root / db ); } return 0; }
virtual void parseObjectRecursive(const BSONObj& object, string& key, int elementIndex=0, int elementCount=1, int arrayIndex = -1, int arrayCount = 0) { stack.push(object, key, elementIndex, elementCount, arrayIndex, arrayCount); visitor.onObjectStart(stack); set<string> keys; object.getFieldNames(keys); // Get the key names of the BSON object. int ei = 0; int ec = keys.size(); for (string key : keys) { BSONElement e = object.getField(key); parseElementRecursive(e, key, ei++, ec, arrayIndex); } visitor.onObjectEnd(stack); stack.drop(); }
int gridfs_listxattr(const char* path, char* list, size_t size) { path = fuse_to_mongo_path(path); if(open_files.find(path) != open_files.end()) { return 0; } ScopedDbConnection sdc(*gridfs_options.conn_string); bool digest = true; string err = ""; sdc.conn().DBClientWithCommands::auth(gridfs_options.db, gridfs_options.username, gridfs_options.password, err, digest); fprintf(stderr, "DEBUG: %s\n", err.c_str()); GridFS gf(sdc.conn(), gridfs_options.db); GridFile file = gf.findFile(path); sdc.done(); if(!file.exists()) { return -ENOENT; } int len = 0; BSONObj metadata = file.getMetadata(); set<string> field_set; metadata.getFieldNames(field_set); for(set<string>::const_iterator s = field_set.begin(); s != field_set.end(); s++) { string attr_name = namespace_xattr(*s); int field_len = attr_name.size() + 1; len += field_len; if(size >= len) { memcpy(list, attr_name.c_str(), field_len); list += field_len; } } if(size == 0) { return len; } else if(size < len) { return -ERANGE; } return len; }
int gridfs_listxattr(const char* path, char* list, size_t size) { path = fuse_to_mongo_path(path); if(open_files.find(path) != open_files.end()) { return 0; } ScopedDbConnection sdc(*gridfs_options.conn_string); ScopedDbConnection_init(sdc); GridFS gf(sdc.conn(), gridfs_options.db, gridfs_options.prefix); GridFile file = gf.findFile(path); sdc.done(); if(!file.exists()) { return -ENOENT; } int len = 0; BSONObj metadata = file.getMetadata(); set<string> field_set; metadata.getFieldNames(field_set); for(set<string>::const_iterator s = field_set.begin(); s != field_set.end(); s++) { string attr_name = namespace_xattr(*s); int field_len = attr_name.size() + 1; len += field_len; if(size >= len) { memcpy(list, attr_name.c_str(), field_len); list += field_len; } } if(size == 0) { return len; } else if(size < len) { return -ERANGE; } return len; }
void simCount(DBClientConnection& c, string dbcoll, BSONObj bobject){ cout<<"\n simCount \n"<< endl; // BSONObj cx = BSONObjBuilder().append(fromjson("{age:12}")).obj(); mongo::BSONObj cx = fromjson("{age: {$gt : 12, $lt : 40}}"); mongo::BSONObj dx = fromjson("{age: {$gt : 12}, age:{$lt : 40}}"); mongo::Query query = QUERY("age"<< NE << 12); auto_ptr<mongo::DBClientCursor> cursor = c.query(dbcoll,dx); set<string> fieldnames; while( cursor->more() ) { BSONObj p = cursor->next(); cout<< p.nFields() <<endl; cout << p.getField("name").toString() << endl; cout << p.getFieldNames(fieldnames) << endl; cout << fieldnames.size() << endl; } }
int run() { bool usingMongos = isMongos(); int serverAuthzVersion = 0; BSONObj dumpQuery; if (mongoDumpGlobalParams.repair){ return repair(); } { if (mongoDumpGlobalParams.query.size()) { dumpQuery = fromjson(mongoDumpGlobalParams.query); } } if (mongoDumpGlobalParams.dumpUsersAndRoles) { uassertStatusOK(auth::getRemoteStoredAuthorizationVersion(&conn(true), &serverAuthzVersion)); uassert(17369, mongoutils::str::stream() << "Backing up users and roles is only supported for " "clusters with auth schema versions 1, 3 or 4; found " << serverAuthzVersion, serverAuthzVersion == AuthorizationManager::schemaVersion24 || serverAuthzVersion == AuthorizationManager::schemaVersion26Final || serverAuthzVersion == AuthorizationManager::schemaVersion28SCRAM); } string opLogName = ""; unsigned long long opLogStart = 0; if (mongoDumpGlobalParams.useOplog) { BSONObj isMaster; conn("true").simpleCommand("admin", &isMaster, "isMaster"); if (isMaster.hasField("hosts")) { // if connected to replica set member opLogName = "local.oplog.rs"; } else { opLogName = "local.oplog.$main"; if ( ! isMaster["ismaster"].trueValue() ) { toolError() << "oplog mode is only supported on master or replica set member" << std::endl; return -1; } } BSONObj op = conn(true).findOne(opLogName, Query().sort("$natural", -1), 0, QueryOption_SlaveOk); if (op.isEmpty()) { toolError() << "No operations in oplog. Please ensure you are connecting to a " << "master." << std::endl; return -1; } verify(op["ts"].type() == Timestamp); opLogStart = op["ts"]._numberLong(); } // check if we're outputting to stdout if (mongoDumpGlobalParams.outputDirectory == "-") { if (toolGlobalParams.db != "" && toolGlobalParams.coll != "") { writeCollectionStdout(toolGlobalParams.db + "." + toolGlobalParams.coll, dumpQuery, usingMongos); return 0; } else { toolError() << "You must specify database and collection to print to stdout" << std::endl; return -1; } } boost::filesystem::path root(mongoDumpGlobalParams.outputDirectory); if (toolGlobalParams.db == "") { if (toolGlobalParams.coll != "") { toolError() << "--db must be specified with --collection" << std::endl; return -1; } toolInfoLog() << "all dbs" << std::endl; BSONObj res = conn( true ).findOne( "admin.$cmd" , BSON( "listDatabases" << 1 ) ); if ( ! res["databases"].isABSONObj() ) { toolError() << "output of listDatabases isn't what we expected, no 'databases' " << "field:\n" << res << std::endl; return -2; } BSONObj dbs = res["databases"].embeddedObjectUserCheck(); set<string> keys; dbs.getFieldNames( keys ); for ( set<string>::iterator i = keys.begin() ; i != keys.end() ; i++ ) { string key = *i; if ( ! dbs[key].isABSONObj() ) { toolError() << "database field not an document key: " << key << " value: " << dbs[key] << std::endl; return -3; } BSONObj dbobj = dbs[key].embeddedObjectUserCheck(); const char * dbName = dbobj.getField( "name" ).valuestr(); if ( (string)dbName == "local" ) continue; boost::filesystem::path outdir = root / dbName; toolInfoLog() << "DATABASE: " << dbName << "\t to \t" << outdir.string() << std::endl; go ( dbName , "", dumpQuery, outdir, "", usingMongos ); } } else { boost::filesystem::path outdir = root / toolGlobalParams.db; toolInfoLog() << "DATABASE: " << toolGlobalParams.db << "\t to \t" << outdir.string() << std::endl; go(toolGlobalParams.db, toolGlobalParams.coll, dumpQuery, outdir, "", usingMongos); if (mongoDumpGlobalParams.dumpUsersAndRoles && serverAuthzVersion >= AuthorizationManager::schemaVersion26Final && toolGlobalParams.db != "admin") { toolInfoLog() << "Backing up user and role data for the " << toolGlobalParams.db << " database"; Query query = Query(BSON("db" << toolGlobalParams.db)); go("admin", "system.users", query, outdir, "$admin.system.users", usingMongos); go("admin", "system.roles", query, outdir, "$admin.system.roles", usingMongos); } } if (!opLogName.empty()) { BSONObjBuilder b; b.appendTimestamp("$gt", opLogStart); dumpQuery = BSON("ts" << b.obj()); writeCollectionFile( opLogName , dumpQuery, root / "oplog.bson", usingMongos ); } return 0; }
int run() { if ( hasParam( "repair" ) ){ warning() << "repair is a work in progress" << endl; return repair(); } { string q = getParam("query"); if ( q.size() ) _query = fromjson( q ); } string opLogName = ""; unsigned long long opLogStart = 0; if (hasParam("oplog")) { if (hasParam("query") || hasParam("db") || hasParam("collection")) { cout << "oplog mode is only supported on full dumps" << endl; return -1; } BSONObj isMaster; conn("true").simpleCommand("admin", &isMaster, "isMaster"); if (isMaster.hasField("hosts")) { // if connected to replica set member opLogName = "local.oplog.rs"; } else { opLogName = "local.oplog.$main"; if ( ! isMaster["ismaster"].trueValue() ) { cout << "oplog mode is only supported on master or replica set member" << endl; return -1; } } auth("local"); BSONObj op = conn(true).findOne(opLogName, Query().sort("$natural", -1), 0, QueryOption_SlaveOk); if (op.isEmpty()) { cout << "No operations in oplog. Please ensure you are connecting to a master." << endl; return -1; } assert(op["ts"].type() == Timestamp); opLogStart = op["ts"]._numberLong(); } // check if we're outputting to stdout string out = getParam("out"); if ( out == "-" ) { if ( _db != "*" && _coll != "*" ) { writeCollectionStdout( _db+"."+_coll ); return 0; } else { cout << "You must specify database and collection to print to stdout" << endl; return -1; } } _usingMongos = isMongos(); path root( out ); string db = _db; if ( db == "*" ) { cout << "all dbs" << endl; auth( "admin" ); BSONObj res = conn( true ).findOne( "admin.$cmd" , BSON( "listDatabases" << 1 ) ); if ( ! res["databases"].isABSONObj() ) { error() << "output of listDatabases isn't what we expected, no 'databases' field:\n" << res << endl; return -2; } BSONObj dbs = res["databases"].embeddedObjectUserCheck(); set<string> keys; dbs.getFieldNames( keys ); for ( set<string>::iterator i = keys.begin() ; i != keys.end() ; i++ ) { string key = *i; if ( ! dbs[key].isABSONObj() ) { error() << "database field not an object key: " << key << " value: " << dbs[key] << endl; return -3; } BSONObj dbobj = dbs[key].embeddedObjectUserCheck(); const char * dbName = dbobj.getField( "name" ).valuestr(); if ( (string)dbName == "local" ) continue; go ( dbName , root / dbName ); } } else { auth( db ); go( db , root / db ); } if (!opLogName.empty()) { BSONObjBuilder b; b.appendTimestamp("$gt", opLogStart); _query = BSON("ts" << b.obj()); writeCollectionFile( opLogName , root / "oplog.bson" ); } return 0; }
/* **************************************************************************** * * ContextElementResponse::ContextElementResponse - * * This constructor builds the CER object based in a BSON object taken from the * entities collection at DB. * * Note that statusCode is not touched by this constructor. */ ContextElementResponse::ContextElementResponse(const mongo::BSONObj& entityDoc, const AttributeList& attrL, bool includeEmpty) { prune = false; // Entity BSONObj id = getField(entityDoc, "_id").embeddedObject(); contextElement.entityId.fill(getStringField(id, ENT_ENTITY_ID), getStringField(id, ENT_ENTITY_TYPE), "false"); contextElement.entityId.servicePath = id.hasField(ENT_SERVICE_PATH) ? getStringField(id, ENT_SERVICE_PATH) : ""; /* Get the location attribute (if it exists) */ std::string locAttr; if (entityDoc.hasElement(ENT_LOCATION)) { locAttr = getStringField(getObjectField(entityDoc, ENT_LOCATION), ENT_LOCATION_ATTRNAME); } // // Attribute vector // FIXME P5: constructor for BSONObj could be added to ContextAttributeVector/ContextAttribute classes, to make building more modular // BSONObj attrs = getField(entityDoc, ENT_ATTRS).embeddedObject(); std::set<std::string> attrNames; attrs.getFieldNames(attrNames); for (std::set<std::string>::iterator i = attrNames.begin(); i != attrNames.end(); ++i) { std::string attrName = *i; BSONObj attr = getField(attrs, attrName).embeddedObject(); ContextAttribute* caP = NULL; ContextAttribute ca; // Name and type ca.name = dbDotDecode(basePart(attrName)); std::string mdId = idPart(attrName); ca.type = getStringField(attr, ENT_ATTRS_TYPE); // Skip attribute if the attribute is in the list (or attrL is empty) if (!includedAttribute(ca, attrL)) { continue; } /* It could happen (although very rarely) that the value field is missing in the * DB for the attribute. The following is a safety check measure to protect against that */ if (!attr.hasField(ENT_ATTRS_VALUE)) { caP = new ContextAttribute(ca.name, ca.type, ""); } else { switch(getField(attr, ENT_ATTRS_VALUE).type()) { case String: ca.stringValue = getStringField(attr, ENT_ATTRS_VALUE); if (!includeEmpty && ca.stringValue.length() == 0) { continue; } caP = new ContextAttribute(ca.name, ca.type, ca.stringValue); break; case NumberDouble: ca.numberValue = getField(attr, ENT_ATTRS_VALUE).Number(); caP = new ContextAttribute(ca.name, ca.type, ca.numberValue); break; case NumberInt: ca.numberValue = (double) getIntField(attr, ENT_ATTRS_VALUE); caP = new ContextAttribute(ca.name, ca.type, ca.numberValue); break; case Bool: ca.boolValue = getBoolField(attr, ENT_ATTRS_VALUE); caP = new ContextAttribute(ca.name, ca.type, ca.boolValue); break; case jstNULL: caP = new ContextAttribute(ca.name, ca.type, ""); caP->valueType = orion::ValueTypeNone; break; case Object: caP = new ContextAttribute(ca.name, ca.type, ""); caP->compoundValueP = new orion::CompoundValueNode(orion::ValueTypeObject); compoundObjectResponse(caP->compoundValueP, getField(attr, ENT_ATTRS_VALUE)); break; case Array: caP = new ContextAttribute(ca.name, ca.type, ""); caP->compoundValueP = new orion::CompoundValueNode(orion::ValueTypeVector); compoundVectorResponse(caP->compoundValueP, getField(attr, ENT_ATTRS_VALUE)); break; default: LM_E(("Runtime Error (unknown attribute value type in DB: %d)", getField(attr, ENT_ATTRS_VALUE).type())); } } /* Setting ID (if found) */ if (mdId != "") { Metadata* md = new Metadata(NGSI_MD_ID, "string", mdId); caP->metadataVector.push_back(md); } /* Setting location metatda (if found) */ if (locAttr == ca.name) { Metadata* md = new Metadata(NGSI_MD_LOCATION, "string", LOCATION_WGS84); caP->metadataVector.push_back(md); } /* Setting custom metadata (if any) */ if (attr.hasField(ENT_ATTRS_MD)) { std::vector<BSONElement> metadataV = getField(attr, ENT_ATTRS_MD).Array(); for (unsigned int ix = 0; ix < metadataV.size(); ++ix) { Metadata* md = new Metadata(metadataV[ix].embeddedObject()); caP->metadataVector.push_back(md); } } contextElement.contextAttributeVector.push_back(caP); } }
/* **************************************************************************** * * ContextElementResponse::ContextElementResponse - * * This constructor builds the CER object based in a BSON object taken from the * entities collection at DB. * * Note that statusCode is not touched by this constructor. */ ContextElementResponse::ContextElementResponse ( const mongo::BSONObj& entityDoc, const AttributeList& attrL, bool includeEmpty, const std::string& apiVersion ) { prune = false; // Entity BSONObj id = getFieldF(entityDoc, "_id").embeddedObject(); std::string entityId = getStringFieldF(id, ENT_ENTITY_ID); std::string entityType = id.hasField(ENT_ENTITY_TYPE) ? getStringFieldF(id, ENT_ENTITY_TYPE) : ""; contextElement.entityId.fill(entityId, entityType, "false"); contextElement.entityId.servicePath = id.hasField(ENT_SERVICE_PATH) ? getStringFieldF(id, ENT_SERVICE_PATH) : ""; /* Get the location attribute (if it exists) */ std::string locAttr; if (entityDoc.hasElement(ENT_LOCATION)) { locAttr = getStringFieldF(getObjectFieldF(entityDoc, ENT_LOCATION), ENT_LOCATION_ATTRNAME); } // // Attribute vector // FIXME P5: constructor for BSONObj could be added to ContextAttributeVector/ContextAttribute classes, to make building more modular // BSONObj attrs = getObjectFieldF(entityDoc, ENT_ATTRS); std::set<std::string> attrNames; attrs.getFieldNames(attrNames); for (std::set<std::string>::iterator i = attrNames.begin(); i != attrNames.end(); ++i) { std::string attrName = *i; BSONObj attr = getObjectFieldF(attrs, attrName); ContextAttribute* caP = NULL; ContextAttribute ca; // Name and type ca.name = dbDotDecode(basePart(attrName)); std::string mdId = idPart(attrName); ca.type = getStringFieldF(attr, ENT_ATTRS_TYPE); // Skip attribute if the attribute is in the list (or attrL is empty or includes "*") if (!includedAttribute(ca, attrL)) { continue; } /* It could happen (although very rarely) that the value field is missing in the * DB for the attribute. The following is a safety check measure to protect against that */ if (!attr.hasField(ENT_ATTRS_VALUE)) { caP = new ContextAttribute(ca.name, ca.type, ""); } else { switch(getFieldF(attr, ENT_ATTRS_VALUE).type()) { case String: ca.stringValue = getStringFieldF(attr, ENT_ATTRS_VALUE); if (!includeEmpty && ca.stringValue.length() == 0) { continue; } caP = new ContextAttribute(ca.name, ca.type, ca.stringValue); break; case NumberDouble: ca.numberValue = getNumberFieldF(attr, ENT_ATTRS_VALUE); caP = new ContextAttribute(ca.name, ca.type, ca.numberValue); break; case NumberInt: ca.numberValue = (double) getIntFieldF(attr, ENT_ATTRS_VALUE); caP = new ContextAttribute(ca.name, ca.type, ca.numberValue); break; case Bool: ca.boolValue = getBoolFieldF(attr, ENT_ATTRS_VALUE); caP = new ContextAttribute(ca.name, ca.type, ca.boolValue); break; case jstNULL: caP = new ContextAttribute(ca.name, ca.type, ""); caP->valueType = orion::ValueTypeNone; break; case Object: caP = new ContextAttribute(ca.name, ca.type, ""); caP->compoundValueP = new orion::CompoundValueNode(orion::ValueTypeObject); caP->valueType = orion::ValueTypeObject; compoundObjectResponse(caP->compoundValueP, getFieldF(attr, ENT_ATTRS_VALUE)); break; case Array: caP = new ContextAttribute(ca.name, ca.type, ""); caP->compoundValueP = new orion::CompoundValueNode(orion::ValueTypeVector); // FIXME P7: next line is counterintuitive. If the object is a vector, why // we need to use ValueTypeObject here? Because otherwise Metadata::toJson() // method doesn't work. A littely crazy... it should be fixed. caP->valueType = orion::ValueTypeObject; compoundVectorResponse(caP->compoundValueP, getFieldF(attr, ENT_ATTRS_VALUE)); break; default: LM_E(("Runtime Error (unknown attribute value type in DB: %d)", getFieldF(attr, ENT_ATTRS_VALUE).type())); } } /* Setting ID (if found) */ if (mdId != "") { Metadata* md = new Metadata(NGSI_MD_ID, "string", mdId); caP->metadataVector.push_back(md); } if (apiVersion == "v1") { /* Setting location metadata (if found) */ if ((locAttr == ca.name) && (ca.type != GEO_POINT)) { /* Note that if attribute type is geo:point then the user is using the "new way" * of locating entities in NGSIv1, thus location metadata is not rendered */ Metadata* md = new Metadata(NGSI_MD_LOCATION, "string", LOCATION_WGS84); caP->metadataVector.push_back(md); } } /* Setting custom metadata (if any) */ if (attr.hasField(ENT_ATTRS_MD)) { BSONObj mds = getObjectFieldF(attr, ENT_ATTRS_MD); std::set<std::string> mdsSet; mds.getFieldNames(mdsSet); for (std::set<std::string>::iterator i = mdsSet.begin(); i != mdsSet.end(); ++i) { std::string currentMd = *i; Metadata* md = new Metadata(dbDotDecode(currentMd), getObjectFieldF(mds, currentMd)); caP->metadataVector.push_back(md); } } /* Set creDate and modDate at attribute level */ if (attr.hasField(ENT_ATTRS_CREATION_DATE)) { caP->creDate = (double) getIntOrLongFieldAsLongF(attr, ENT_ATTRS_CREATION_DATE); } if (attr.hasField(ENT_ATTRS_MODIFICATION_DATE)) { caP->modDate = (double) getIntOrLongFieldAsLongF(attr, ENT_ATTRS_MODIFICATION_DATE); } contextElement.contextAttributeVector.push_back(caP); } /* Set creDate and modDate at entity level */ if (entityDoc.hasField(ENT_CREATION_DATE)) { contextElement.entityId.creDate = (double) getIntOrLongFieldAsLongF(entityDoc, ENT_CREATION_DATE); } if (entityDoc.hasField(ENT_MODIFICATION_DATE)) { contextElement.entityId.modDate = (double) getIntOrLongFieldAsLongF(entityDoc, ENT_MODIFICATION_DATE); } }
QueryPlan::QueryPlan( const FieldBoundSet &fbs, const BSONObj &order, const IndexDetails *index ) : fbs_( fbs ), order_( order ), index_( index ), optimal_( false ), scanAndOrderRequired_( true ), keyMatch_( false ), exactKeyMatch_( false ), direction_( 0 ), unhelpful_( false ) { // full table scan case if ( !index_ ) { if ( order_.isEmpty() || !strcmp( order_.firstElement().fieldName(), "$natural" ) ) scanAndOrderRequired_ = false; return; } BSONObj idxKey = index->keyPattern(); BSONObjIterator o( order ); BSONObjIterator k( idxKey ); if ( !o.more() ) scanAndOrderRequired_ = false; while( o.more() ) { BSONElement oe = o.next(); if ( oe.eoo() ) { scanAndOrderRequired_ = false; break; } if ( !k.more() ) break; BSONElement ke; while( 1 ) { ke = k.next(); if ( ke.eoo() ) goto doneCheckOrder; if ( strcmp( oe.fieldName(), ke.fieldName() ) == 0 ) break; if ( !fbs.bound( ke.fieldName() ).equality() ) goto doneCheckOrder; } int d = oe.number() == ke.number() ? 1 : -1; if ( direction_ == 0 ) direction_ = d; else if ( direction_ != d ) break; } doneCheckOrder: if ( scanAndOrderRequired_ ) direction_ = 0; BSONObjIterator i( idxKey ); int indexedQueryCount = 0; int exactIndexedQueryCount = 0; int optimalIndexedQueryCount = 0; bool stillOptimalIndexedQueryCount = true; set< string > orderFieldsUnindexed; order.getFieldNames( orderFieldsUnindexed ); BSONObjBuilder startKeyBuilder; BSONObjBuilder endKeyBuilder; while( i.more() ) { BSONElement e = i.next(); if ( e.eoo() ) break; const FieldBound &fb = fbs.bound( e.fieldName() ); int number = (int) e.number(); // returns 0.0 if not numeric bool forward = ( ( number >= 0 ? 1 : -1 ) * ( direction_ >= 0 ? 1 : -1 ) > 0 ); startKeyBuilder.appendAs( forward ? fb.lower() : fb.upper(), "" ); endKeyBuilder.appendAs( forward ? fb.upper() : fb.lower(), "" ); if ( fb.nontrivial() ) ++indexedQueryCount; if ( stillOptimalIndexedQueryCount ) { if ( fb.nontrivial() ) ++optimalIndexedQueryCount; if ( !fb.equality() ) stillOptimalIndexedQueryCount = false; } else { if ( fb.nontrivial() ) optimalIndexedQueryCount = -1; } if ( fb.equality() ) { BSONElement e = fb.upper(); if ( !e.isNumber() && !e.mayEncapsulate() && e.type() != RegEx ) ++exactIndexedQueryCount; } orderFieldsUnindexed.erase( e.fieldName() ); } if ( !scanAndOrderRequired_ && ( optimalIndexedQueryCount == fbs.nNontrivialBounds() ) ) optimal_ = true; if ( indexedQueryCount == fbs.nNontrivialBounds() && orderFieldsUnindexed.size() == 0 ) { keyMatch_ = true; if ( exactIndexedQueryCount == fbs.nNontrivialBounds() ) exactKeyMatch_ = true; } startKey_ = startKeyBuilder.obj(); endKey_ = endKeyBuilder.obj(); if ( !keyMatch_ && ( scanAndOrderRequired_ || order_.isEmpty() ) && !fbs.bound( idxKey.firstElement().fieldName() ).nontrivial() ) unhelpful_ = true; }