bool applyProjectionToOneField(StringData field) const { MutableDocument doc; const FieldPath f{field}; doc.setNestedField(f, Value(1.0)); const Document transformedDoc = applyTransformation(doc.freeze()); return !transformedDoc.getNestedField(f).missing(); }
boost::optional<Document> DocumentSourceGeoNear::getNext() { pExpCtx->checkForInterrupt(); if (!resultsIterator) runCommand(); if (!resultsIterator->more()) return boost::none; // each result from the geoNear command is wrapped in a wrapper object with "obj", // "dis" and maybe "loc" fields. We want to take the object from "obj" and inject the // other fields into it. Document result (resultsIterator->next().embeddedObject()); MutableDocument output (result["obj"].getDocument()); output.setNestedField(*distanceField, result["dis"]); if (includeLocs) output.setNestedField(*includeLocs, result["loc"]); return output.freeze(); }
// Taken as a whole, these three functions should produce the same output document given the // same deps set as mongo::Projection::transform would on the output of depsToProjection. The // only exceptions are that we correctly handle the case where no fields are needed and we don't // need to work around the above mentioned bug with subfields of _id (SERVER-7502). This is // tested in a DEV block in DocumentSourceCursor::findNext(). // // Output from this function is input for the next two // // ParsedDeps is a simple recursive look-up table. For each field in a ParsedDeps: // If the value has type==Bool, the whole field is needed // If the value has type==Object, the fields in the subobject are needed // All other fields should be missing which means not needed DocumentSource::ParsedDeps DocumentSource::parseDeps(const set<string>& deps) { MutableDocument md; string last; for (set<string>::const_iterator it(deps.begin()), end(deps.end()); it!=end; ++it) { if (!last.empty() && str::startsWith(*it, last)) { // we are including a parent of *it so we don't need to include this field // explicitly. In fact, if we included this field, the parent wouldn't be fully // included. This logic relies on on set iterators going in lexicographic order so // that a string is always directly before of all fields it prefixes. continue; } last = *it + '.'; md.setNestedField(*it, Value(true)); } return md.freeze(); }
// ParsedDeps::_fields is a simple recursive look-up table. For each field: // If the value has type==Bool, the whole field is needed // If the value has type==Object, the fields in the subobject are needed // All other fields should be missing which means not needed boost::optional<ParsedDeps> DepsTracker::toParsedDeps() const { MutableDocument md; if (needWholeDocument || _needTextScore) { // can't use ParsedDeps in this case return boost::none; } string last; for (set<string>::const_iterator it(fields.begin()), end(fields.end()); it != end; ++it) { if (!last.empty() && str::startsWith(*it, last)) { // we are including a parent of *it so we don't need to include this field // explicitly. In fact, if we included this field, the parent wouldn't be fully // included. This logic relies on on set iterators going in lexicographic order so // that a string is always directly before of all fields it prefixes. continue; } last = *it + '.'; md.setNestedField(*it, Value(true)); } return ParsedDeps(md.freeze()); }