本文整理汇总了C++中BSONObj::getFieldsDotted方法的典型用法代码示例。如果您正苦于以下问题:C++ BSONObj::getFieldsDotted方法的具体用法?C++ BSONObj::getFieldsDotted怎么用?C++ BSONObj::getFieldsDotted使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类BSONObj
的用法示例。
在下文中一共展示了BSONObj::getFieldsDotted方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: getKeys
void getKeys( const BSONObj &obj, BSONObjSet &keys ) const {
BSONElement loc = obj.getFieldDotted( _geo );
if ( loc.eoo() )
return;
uassert( 13323 , "latlng not an array" , loc.isABSONObj() );
string root;
{
BSONObjIterator i( loc.Obj() );
BSONElement x = i.next();
BSONElement y = i.next();
root = makeString( hash(x) , hash(y) );
}
verify( _other.size() == 1 );
BSONElementSet all;
obj.getFieldsDotted( _other[0] , all );
if ( all.size() == 0 ) {
_add( obj , root , BSONElement() , keys );
}
else {
for ( BSONElementSet::iterator i=all.begin(); i!=all.end(); ++i ) {
_add( obj , root , *i , keys );
}
}
}
示例2: getKeys
void getKeys(const BSONObj& obj, BSONObjSet& keys) const {
verify(_fields.size() >= 1);
BSONObjSet keysToAdd;
// We output keys in the same order as the fields we index.
for (size_t i = 0; i < _fields.size(); ++i) {
const IndexedField &field = _fields[i];
// First, we get the keys that this field adds. Either they're added literally from
// the value of the field, or they're transformed if the field is geo.
BSONElementSet fieldElements;
// false means Don't expand the last array, duh.
obj.getFieldsDotted(field.name, fieldElements, false);
BSONObjSet keysForThisField;
if (IndexedField::GEO == field.type) {
getGeoKeys(fieldElements, &keysForThisField);
} else if (IndexedField::LITERAL == field.type) {
getLiteralKeys(fieldElements, &keysForThisField);
} else {
verify(0);
}
// We expect there to be _spec->_missingField() present in the keys if data is
// missing. So, this should be non-empty.
verify(!keysForThisField.empty());
// We take the Cartesian product of all of the keys. This requires that we have
// some keys to take the Cartesian product with. If keysToAdd.empty(), we
// initialize it.
if (keysToAdd.empty()) {
keysToAdd = keysForThisField;
continue;
}
BSONObjSet updatedKeysToAdd;
for (BSONObjSet::const_iterator it = keysToAdd.begin(); it != keysToAdd.end();
++it) {
for (BSONObjSet::const_iterator newIt = keysForThisField.begin();
newIt!= keysForThisField.end(); ++newIt) {
BSONObjBuilder b;
b.appendElements(*it);
b.append(newIt->firstElement());
updatedKeysToAdd.insert(b.obj());
}
}
keysToAdd = updatedKeysToAdd;
}
if (keysToAdd.size() > _params.maxKeysPerInsert) {
warning() << "insert of geo object generated lots of keys (" << keysToAdd.size()
<< ") consider creating larger buckets. obj="
<< obj;
}
for (BSONObjSet::const_iterator it = keysToAdd.begin(); it != keysToAdd.end(); ++it) {
keys.insert(*it);
}
}
示例3: i
void S2AccessMethod::getKeys(const BSONObj& obj, BSONObjSet* keys) {
BSONObjSet keysToAdd;
// We output keys in the same order as the fields we index.
BSONObjIterator i(_descriptor->keyPattern());
while (i.more()) {
BSONElement e = i.next();
// First, we get the keys that this field adds. Either they're added literally from
// the value of the field, or they're transformed if the field is geo.
BSONElementSet fieldElements;
// false means Don't expand the last array, duh.
obj.getFieldsDotted(e.fieldName(), fieldElements, false);
BSONObjSet keysForThisField;
if (IndexNames::GEO_2DSPHERE == e.valuestr()) {
// We can't ever return documents that don't have geometry so don't bother indexing
// them.
if (fieldElements.empty()) { return; }
getGeoKeys(obj, fieldElements, &keysForThisField);
} else {
getLiteralKeys(fieldElements, &keysForThisField);
}
// We expect there to be the missing field element present in the keys if data is
// missing. So, this should be non-empty.
verify(!keysForThisField.empty());
// We take the Cartesian product of all of the keys. This requires that we have
// some keys to take the Cartesian product with. If keysToAdd.empty(), we
// initialize it.
if (keysToAdd.empty()) {
keysToAdd = keysForThisField;
continue;
}
BSONObjSet updatedKeysToAdd;
for (BSONObjSet::const_iterator it = keysToAdd.begin(); it != keysToAdd.end();
++it) {
for (BSONObjSet::const_iterator newIt = keysForThisField.begin();
newIt!= keysForThisField.end(); ++newIt) {
BSONObjBuilder b;
b.appendElements(*it);
b.append(newIt->firstElement());
updatedKeysToAdd.insert(b.obj());
}
}
keysToAdd = updatedKeysToAdd;
}
if (keysToAdd.size() > _params.maxKeysPerInsert) {
warning() << "insert of geo object generated lots of keys (" << keysToAdd.size()
<< ") consider creating larger buckets. obj="
<< obj;
}
*keys = keysToAdd;
}
示例4: matches
bool AllElemMatchOp::matches( const BSONObj& doc, MatchDetails* details ) const {
BSONElementSet all;
doc.getFieldsDotted( _path, all, false );
for ( BSONElementSet::const_iterator i = all.begin(); i != all.end(); ++i ) {
BSONElement sub = *i;
if ( sub.type() != Array )
continue;
if ( _allMatch( sub.Obj() ) ) {
return true;
}
}
return false;
}
示例5: getHaystackKeys
// static
void ExpressionKeysPrivate::getHaystackKeys(const BSONObj& obj,
const std::string& geoField,
const std::vector<std::string>& otherFields,
double bucketSize,
BSONObjSet* keys) {
BSONElement loc = obj.getFieldDotted(geoField);
if (loc.eoo()) {
return;
}
// NOTE: We explicitly test nFields >= 2 to support legacy users who may have indexed
// (intentionally or unintentionally) objects/arrays with more than two fields.
uassert(16775,
str::stream() << "cannot extract [lng, lat] array or object from " << obj,
loc.isABSONObj() && loc.Obj().nFields() >= 2);
string root;
{
BSONObjIterator i(loc.Obj());
BSONElement x = i.next();
BSONElement y = i.next();
root = makeHaystackString(hashHaystackElement(x, bucketSize),
hashHaystackElement(y, bucketSize));
}
verify(otherFields.size() == 1);
BSONElementSet all;
// This is getFieldsDotted (plural not singular) since the object we're indexing
// may be an array.
obj.getFieldsDotted(otherFields[0], all);
if (all.size() == 0) {
// We're indexing a document that doesn't have the secondary non-geo field present.
// XXX: do we want to add this even if all.size() > 0? result:empty search terms
// match everything instead of only things w/empty search terms)
addKey(root, BSONElement(), keys);
} else {
// Ex:If our secondary field is type: "foo" or type: {a:"foo", b:"bar"},
// all.size()==1. We can query on the complete field.
// Ex: If our secondary field is type: ["A", "B"] all.size()==2 and all has values
// "A" and "B". The query looks for any of the fields in the array.
for (BSONElementSet::iterator i = all.begin(); i != all.end(); ++i) {
addKey(root, *i, keys);
}
}
}
示例6: extractGeometries
/**
* Find and parse all geometry elements on the appropriate field path from the document.
*/
static void extractGeometries(const BSONObj& doc,
const string& path,
vector<StoredGeometry*>* geometries) {
BSONElementSet geomElements;
// NOTE: Annoyingly, we cannot just expand arrays b/c single 2d points are arrays, we need
// to manually expand all results to check if they are geometries
doc.getFieldsDotted(path, geomElements, false /* expand arrays */);
for (BSONElementSet::iterator it = geomElements.begin(); it != geomElements.end(); ++it) {
const BSONElement& el = *it;
auto_ptr<StoredGeometry> stored(StoredGeometry::parseFrom(el));
if (stored.get()) {
// Valid geometry element
geometries->push_back(stored.release());
}
else if (el.type() == Array) {
// Many geometries may be in an array
BSONObjIterator arrIt(el.Obj());
while (arrIt.more()) {
const BSONElement nextEl = arrIt.next();
stored.reset(StoredGeometry::parseFrom(nextEl));
if (stored.get()) {
// Valid geometry element
geometries->push_back(stored.release());
}
else {
warning() << "geoNear stage read non-geometry element " << nextEl.toString()
<< " in array " << el.toString();
}
}
}
else {
warning() << "geoNear stage read non-geometry element " << el.toString();
}
}
}
示例7: getKeys
void getKeys(const BSONObj &obj, BSONObjSet &keys) const {
BSONElement loc = obj.getFieldDotted(_geoField);
if (loc.eoo())
return;
uassert(13323, "latlng not an array", loc.isABSONObj());
string root;
{
BSONObjIterator i(loc.Obj());
BSONElement x = i.next();
BSONElement y = i.next();
root = makeString(hash(x), hash(y));
}
verify(_otherFields.size() == 1);
BSONElementSet all;
// This is getFieldsDotted (plural not singular) since the object we're indexing
// may be an array.
obj.getFieldsDotted(_otherFields[0], all);
if (all.size() == 0) {
// We're indexing a document that doesn't have the secondary non-geo field present.
// XXX: do we want to add this even if all.size() > 0? result:empty search terms
// match everything instead of only things w/empty search terms)
addKey(root, BSONElement(), keys);
} else {
// Ex:If our secondary field is type: "foo" or type: {a:"foo", b:"bar"},
// all.size()==1. We can query on the complete field.
// Ex: If our secondary field is type: ["A", "B"] all.size()==2 and all has values
// "A" and "B". The query looks for any of the fields in the array.
for (BSONElementSet::iterator i = all.begin(); i != all.end(); ++i) {
addKey(root, *i, keys);
}
}
}
示例8: run
bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ){
string ns = dbname + '.' + cmdObj.firstElement().valuestr();
string key = cmdObj["key"].valuestrsafe();
BSONObj keyPattern = BSON( key << 1 );
BSONObj query = getQuery( cmdObj );
BSONElementSet values;
shared_ptr<Cursor> cursor = bestGuessCursor(ns.c_str() , query , BSONObj() );
scoped_ptr<ClientCursor> cc (new ClientCursor(QueryOption_NoCursorTimeout, cursor, ns));
while ( cursor->ok() ){
if ( !cursor->matcher() || cursor->matcher()->matchesCurrent( cursor.get() ) ){
BSONObj o = cursor->current();
o.getFieldsDotted( key, values );
}
cursor->advance();
if (!cc->yieldSometimes())
break;
RARELY killCurrentOp.checkForInterrupt();
}
BSONArrayBuilder b( result.subarrayStart( "values" ) );
for ( BSONElementSet::iterator i = values.begin() ; i != values.end(); i++ ){
b.append( *i );
}
BSONObj arr = b.done();
uassert(10044, "distinct too big, 4mb cap", arr.objsize() < BSONObjMaxUserSize );
return true;
}
示例9: i
void ExpressionKeysPrivate::getS2Keys(const BSONObj& obj,
const BSONObj& keyPattern,
const S2IndexingParams& params,
BSONObjSet* keys) {
BSONObjSet keysToAdd;
// Does one of our documents have a geo field?
bool haveGeoField = false;
// We output keys in the same order as the fields we index.
BSONObjIterator i(keyPattern);
while (i.more()) {
BSONElement e = i.next();
// First, we get the keys that this field adds. Either they're added literally from
// the value of the field, or they're transformed if the field is geo.
BSONElementSet fieldElements;
// false means Don't expand the last array, duh.
obj.getFieldsDotted(e.fieldName(), fieldElements, false);
BSONObjSet keysForThisField;
if (IndexNames::GEO_2DSPHERE == e.valuestr()) {
if (params.indexVersion >= S2_INDEX_VERSION_2) {
// For >= V2,
// geo: null,
// geo: undefined
// geo: []
// should all behave like there is no geo field. So we look for these cases and
// throw out the field elements if we find them.
if (1 == fieldElements.size()) {
BSONElement elt = *fieldElements.begin();
// Get the :null and :undefined cases.
if (elt.isNull() || Undefined == elt.type()) {
fieldElements.clear();
} else if (elt.isABSONObj()) {
// And this is the :[] case.
BSONObj obj = elt.Obj();
if (0 == obj.nFields()) {
fieldElements.clear();
}
}
}
// >= V2 2dsphere indices require that at least one geo field to be present in a
// document in order to index it.
if (fieldElements.size() > 0) {
haveGeoField = true;
}
}
getS2GeoKeys(obj, fieldElements, params, &keysForThisField);
} else {
getS2LiteralKeys(fieldElements, params.collator, &keysForThisField);
}
// We expect there to be the missing field element present in the keys if data is
// missing. So, this should be non-empty.
verify(!keysForThisField.empty());
// We take the Cartesian product of all of the keys. This requires that we have
// some keys to take the Cartesian product with. If keysToAdd.empty(), we
// initialize it.
if (keysToAdd.empty()) {
keysToAdd = keysForThisField;
continue;
}
BSONObjSet updatedKeysToAdd;
for (BSONObjSet::const_iterator it = keysToAdd.begin(); it != keysToAdd.end(); ++it) {
for (BSONObjSet::const_iterator newIt = keysForThisField.begin();
newIt != keysForThisField.end();
++newIt) {
BSONObjBuilder b;
b.appendElements(*it);
b.append(newIt->firstElement());
updatedKeysToAdd.insert(b.obj());
}
}
keysToAdd = updatedKeysToAdd;
}
// Make sure that if we're >= V2 there's at least one geo field present in the doc.
if (params.indexVersion >= S2_INDEX_VERSION_2) {
if (!haveGeoField) {
return;
}
}
if (keysToAdd.size() > params.maxKeysPerInsert) {
warning() << "Insert of geo object generated a high number of keys."
<< " num keys: " << keysToAdd.size() << " obj inserted: " << obj;
}
*keys = keysToAdd;
}
示例10: 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;
}
}
//.........这里部分代码省略.........
示例11: i
static bool run2DSphereGeoNear(NamespaceDetails* nsDetails, int idxNo, BSONObj& cmdObj,
const GeoNearArguments &parsedArgs, string& errmsg,
BSONObjBuilder& result) {
auto_ptr<IndexDescriptor> descriptor(CatalogHack::getDescriptor(nsDetails, idxNo));
auto_ptr<S2AccessMethod> sam(new S2AccessMethod(descriptor.get()));
const S2IndexingParams& params = sam->getParams();
auto_ptr<S2NearIndexCursor> nic(new S2NearIndexCursor(descriptor.get(), params));
vector<string> geoFieldNames;
BSONObjIterator i(descriptor->keyPattern());
while (i.more()) {
BSONElement e = i.next();
if (e.type() == String && IndexNames::GEO_2DSPHERE == e.valuestr()) {
geoFieldNames.push_back(e.fieldName());
}
}
// NOTE(hk): If we add a new argument to geoNear, we could have a
// 2dsphere index with multiple indexed geo fields, and the geoNear
// could pick the one to run over. Right now, we just require one.
uassert(16552, "geoNear requires exactly one indexed geo field", 1 == geoFieldNames.size());
NearQuery nearQuery(geoFieldNames[0]);
uassert(16679, "Invalid geometry given as arguments to geoNear: " + cmdObj.toString(),
nearQuery.parseFromGeoNear(cmdObj, params.radius));
uassert(16683, "geoNear on 2dsphere index requires spherical",
parsedArgs.isSpherical);
// NOTE(hk): For a speedup, we could look through the query to see if
// we've geo-indexed any of the fields in it.
vector<GeoQuery> regions;
nic->seek(parsedArgs.query, nearQuery, regions);
// We do pass in the query above, but it's just so we can possibly use it in our index
// scan. We have to do our own matching.
auto_ptr<Matcher> matcher(new Matcher(parsedArgs.query));
double totalDistance = 0;
BSONObjBuilder resultBuilder(result.subarrayStart("results"));
double farthestDist = 0;
int results;
for (results = 0; results < parsedArgs.numWanted && !nic->isEOF(); ++results) {
BSONObj currObj = nic->getValue().obj();
if (!matcher->matches(currObj)) {
--results;
nic->next();
continue;
}
double dist = nic->currentDistance();
// If we got the distance in radians, output it in radians too.
if (nearQuery.fromRadians) { dist /= params.radius; }
dist *= parsedArgs.distanceMultiplier;
totalDistance += dist;
if (dist > farthestDist) { farthestDist = dist; }
BSONObjBuilder oneResultBuilder(
resultBuilder.subobjStart(BSONObjBuilder::numStr(results)));
oneResultBuilder.append("dis", dist);
if (parsedArgs.includeLocs) {
BSONElementSet geoFieldElements;
currObj.getFieldsDotted(geoFieldNames[0], geoFieldElements, false);
for (BSONElementSet::iterator oi = geoFieldElements.begin();
oi != geoFieldElements.end(); ++oi) {
if (oi->isABSONObj()) {
oneResultBuilder.appendAs(*oi, "loc");
}
}
}
oneResultBuilder.append("obj", currObj);
oneResultBuilder.done();
nic->next();
}
resultBuilder.done();
BSONObjBuilder stats(result.subobjStart("stats"));
stats.appendNumber("nscanned", nic->nscanned());
stats.append("avgDistance", totalDistance / results);
stats.append("maxDistance", farthestDist);
stats.append("time", cc().curop()->elapsedMillis());
stats.done();
return true;
}
示例12: 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
NamespaceDetails * d = nsdetails( ns );
string cursorName;
if (!d) {
result.appendArray( "values" , BSONObj() );
result.append("stats", BSON("n" << 0 <<
"nscanned" << 0 <<
"nscannedObjects" << 0));
return true;
}
CanonicalQuery* cq;
// XXX: project out just the field we're distinct-ing. May be covered...
if (!CanonicalQuery::canonicalize(ns, query, &cq).isOK()) {
uasserted(17215, "Can't canonicalize query " + query.toString());
return 0;
}
Runner* rawRunner;
if (!getRunner(cq, &rawRunner).isOK()) {
uasserted(17216, "Can't get runner for query " + query.toString());
return 0;
}
auto_ptr<Runner> runner(rawRunner);
auto_ptr<DeregisterEvenIfUnderlyingCodeThrows> safety;
ClientCursor::registerRunner(runner.get());
runner->setYieldPolicy(Runner::YIELD_AUTO);
safety.reset(new DeregisterEvenIfUnderlyingCodeThrows(runner.get()));
BSONObj obj;
Runner::RunnerState state;
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
BSONElementSet elts;
obj.getFieldsDotted(key, elts);
for (BSONElementSet::iterator it = elts.begin(); it != elts.end(); ++it) {
BSONElement elt = *it;
if (values.count(elt)) { continue; }
int currentBufPos = bb.len();
uassert(17217, "distinct too big, 16mb cap",
(currentBufPos + elt.size() + 1024) < bufSize);
arr.append(elt);
BSONElement x(start + currentBufPos);
values.insert(x);
}
}
TypeExplain* bareExplain;
Status res = runner->getExplainPlan(&bareExplain);
if (res.isOK()) {
auto_ptr<TypeExplain> explain(bareExplain);
if (explain->isCursorSet()) {
cursorName = explain->getCursor();
}
n = explain->getN();
nscanned = explain->getNScanned();
nscannedObjects = explain->getNScannedObjects();
}
verify( start == bb.buf() );
result.appendArray( "values" , arr.done() );
{
BSONObjBuilder b;
b.appendNumber( "n" , n );
b.appendNumber( "nscanned" , nscanned );
b.appendNumber( "nscannedObjects" , nscannedObjects );
b.appendNumber( "timems" , t.millis() );
b.append( "cursor" , cursorName );
result.append( "stats" , b.obj() );
}
return true;
}
示例13: run
bool run(OperationContext* txn,
const string& dbname,
BSONObj& cmdObj,
int,
string& errmsg,
BSONObjBuilder& result) {
Timer t;
// ensure that the key is a string
uassert(18510,
mongoutils::str::stream() << "The first argument to the distinct command "
<< "must be a string but was a "
<< typeName(cmdObj["key"].type()),
cmdObj["key"].type() == mongo::String);
// ensure that the where clause is a document
if (cmdObj["query"].isNull() == false && cmdObj["query"].eoo() == false) {
uassert(18511,
mongoutils::str::stream() << "The query for the distinct command must be a "
<< "document but was a "
<< typeName(cmdObj["query"].type()),
cmdObj["query"].type() == mongo::Object);
}
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;
const string ns = parseNs(dbname, cmdObj);
AutoGetCollectionForRead ctx(txn, ns);
Collection* collection = ctx.getCollection();
if (!collection) {
result.appendArray("values", BSONObj());
result.append("stats", BSON("n" << 0 << "nscanned" << 0 << "nscannedObjects" << 0));
return true;
}
auto statusWithPlanExecutor =
getExecutorDistinct(txn, collection, query, key, PlanExecutor::YIELD_AUTO);
if (!statusWithPlanExecutor.isOK()) {
uasserted(17216,
mongoutils::str::stream() << "Can't get executor for query " << query << ": "
<< statusWithPlanExecutor.getStatus().toString());
return 0;
}
unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());
BSONObj obj;
PlanExecutor::ExecState state;
while (PlanExecutor::ADVANCED == (state = exec->getNext(&obj, NULL))) {
// Distinct expands arrays.
//
// If our query is covered, each value of the key should be in the index key and
// available to us without this. If a collection scan is providing the data, we may
// have to expand an array.
BSONElementSet elts;
obj.getFieldsDotted(key, elts);
for (BSONElementSet::iterator it = elts.begin(); it != elts.end(); ++it) {
BSONElement elt = *it;
if (values.count(elt)) {
continue;
}
int currentBufPos = bb.len();
uassert(17217,
"distinct too big, 16mb cap",
(currentBufPos + elt.size() + 1024) < bufSize);
arr.append(elt);
BSONElement x(start + currentBufPos);
values.insert(x);
}
}
// Get summary information about the plan.
PlanSummaryStats stats;
Explain::getSummaryStats(*exec, &stats);
verify(start == bb.buf());
result.appendArray("values", arr.done());
{
BSONObjBuilder b;
b.appendNumber("n", stats.nReturned);
b.appendNumber("nscanned", stats.totalKeysExamined);
b.appendNumber("nscannedObjects", stats.totalDocsExamined);
b.appendNumber("timems", t.millis());
b.append("planSummary", Explain::getPlanSummary(exec.get()));
//.........这里部分代码省略.........
示例14: 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
Collection* collection = cc().database()->getCollection( ns );
if (!collection) {
result.appendArray( "values" , BSONObj() );
result.append("stats", BSON("n" << 0 <<
"nscanned" << 0 <<
"nscannedObjects" << 0));
return true;
}
Runner* rawRunner;
Status status = getRunnerDistinct(collection, query, key, &rawRunner);
if (!status.isOK()) {
uasserted(17216, mongoutils::str::stream() << "Can't get runner for query "
<< query << ": " << status.toString());
return 0;
}
auto_ptr<Runner> runner(rawRunner);
const ScopedRunnerRegistration safety(runner.get());
runner->setYieldPolicy(Runner::YIELD_AUTO);
string cursorName;
BSONObj obj;
Runner::RunnerState state;
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
// Distinct expands arrays.
//
// If our query is covered, each value of the key should be in the index key and
// available to us without this. If a collection scan is providing the data, we may
// have to expand an array.
BSONElementSet elts;
obj.getFieldsDotted(key, elts);
for (BSONElementSet::iterator it = elts.begin(); it != elts.end(); ++it) {
BSONElement elt = *it;
if (values.count(elt)) { continue; }
int currentBufPos = bb.len();
uassert(17217, "distinct too big, 16mb cap",
(currentBufPos + elt.size() + 1024) < bufSize);
arr.append(elt);
BSONElement x(start + currentBufPos);
values.insert(x);
}
}
TypeExplain* bareExplain;
Status res = runner->getInfo(&bareExplain, NULL);
if (res.isOK()) {
auto_ptr<TypeExplain> explain(bareExplain);
if (explain->isCursorSet()) {
cursorName = explain->getCursor();
}
n = explain->getN();
nscanned = explain->getNScanned();
nscannedObjects = explain->getNScannedObjects();
}
verify( start == bb.buf() );
result.appendArray( "values" , arr.done() );
{
BSONObjBuilder b;
b.appendNumber( "n" , n );
b.appendNumber( "nscanned" , nscanned );
b.appendNumber( "nscannedObjects" , nscannedObjects );
b.appendNumber( "timems" , t.millis() );
b.append( "cursor" , cursorName );
result.append( "stats" , b.obj() );
}
return true;
}
示例15: run
bool run(OperationContext* txn,
const string& dbname,
BSONObj& cmdObj,
int,
string& errmsg,
BSONObjBuilder& result) {
Timer t;
const string ns = parseNs(dbname, cmdObj);
AutoGetCollectionForRead ctx(txn, ns);
Collection* collection = ctx.getCollection();
auto executor = getPlanExecutor(txn, collection, ns, cmdObj, false);
if (!executor.isOK()) {
return appendCommandStatus(result, executor.getStatus());
}
string key = cmdObj[kKeyField].valuestrsafe();
int bufSize = BSONObjMaxUserSize - 4096;
BufBuilder bb(bufSize);
char* start = bb.buf();
BSONArrayBuilder arr(bb);
BSONElementSet values;
BSONObj obj;
PlanExecutor::ExecState state;
while (PlanExecutor::ADVANCED == (state = executor.getValue()->getNext(&obj, NULL))) {
// Distinct expands arrays.
//
// If our query is covered, each value of the key should be in the index key and
// available to us without this. If a collection scan is providing the data, we may
// have to expand an array.
BSONElementSet elts;
obj.getFieldsDotted(key, elts);
for (BSONElementSet::iterator it = elts.begin(); it != elts.end(); ++it) {
BSONElement elt = *it;
if (values.count(elt)) {
continue;
}
int currentBufPos = bb.len();
uassert(17217,
"distinct too big, 16mb cap",
(currentBufPos + elt.size() + 1024) < bufSize);
arr.append(elt);
BSONElement x(start + currentBufPos);
values.insert(x);
}
}
// Return an error if execution fails for any reason.
if (PlanExecutor::FAILURE == state || PlanExecutor::DEAD == state) {
const std::unique_ptr<PlanStageStats> stats(executor.getValue()->getStats());
log() << "Plan executor error during distinct command: "
<< PlanExecutor::statestr(state) << ", stats: " << Explain::statsToBSON(*stats);
return appendCommandStatus(result,
Status(ErrorCodes::OperationFailed,
str::stream()
<< "Executor error during distinct command: "
<< WorkingSetCommon::toStatusString(obj)));
}
// Get summary information about the plan.
PlanSummaryStats stats;
Explain::getSummaryStats(*executor.getValue(), &stats);
collection->infoCache()->notifyOfQuery(txn, stats.indexesUsed);
CurOp::get(txn)->debug().fromMultiPlanner = stats.fromMultiPlanner;
CurOp::get(txn)->debug().replanned = stats.replanned;
verify(start == bb.buf());
result.appendArray("values", arr.done());
{
BSONObjBuilder b;
b.appendNumber("n", stats.nReturned);
b.appendNumber("nscanned", stats.totalKeysExamined);
b.appendNumber("nscannedObjects", stats.totalDocsExamined);
b.appendNumber("timems", t.millis());
b.append("planSummary", Explain::getPlanSummary(executor.getValue().get()));
result.append("stats", b.obj());
}
return true;
}