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();
    }
Exemple #3
0
    // 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();
    }
Exemple #4
0
// 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());
}