summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/dependencies.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline/dependencies.cpp')
-rw-r--r--src/mongo/db/pipeline/dependencies.cpp224
1 files changed, 113 insertions, 111 deletions
diff --git a/src/mongo/db/pipeline/dependencies.cpp b/src/mongo/db/pipeline/dependencies.cpp
index 128d46bd703..30ced50e06a 100644
--- a/src/mongo/db/pipeline/dependencies.cpp
+++ b/src/mongo/db/pipeline/dependencies.cpp
@@ -35,146 +35,148 @@
namespace mongo {
- using std::set;
- using std::string;
- using std::vector;
+using std::set;
+using std::string;
+using std::vector;
- namespace str = mongoutils::str;
+namespace str = mongoutils::str;
- BSONObj DepsTracker::toProjection() const {
- BSONObjBuilder bb;
+BSONObj DepsTracker::toProjection() const {
+ BSONObjBuilder bb;
- if (needTextScore)
- bb.append(Document::metaFieldTextScore, BSON("$meta" << "textScore"));
+ if (needTextScore)
+ bb.append(Document::metaFieldTextScore,
+ BSON("$meta"
+ << "textScore"));
- if (needWholeDocument)
- return bb.obj();
+ if (needWholeDocument)
+ return bb.obj();
- if (fields.empty()) {
- // Projection language lacks good a way to say no fields needed. This fakes it.
- bb.append("_id", 0);
- bb.append("$noFieldsNeeded", 1);
- return bb.obj();
- }
+ if (fields.empty()) {
+ // Projection language lacks good a way to say no fields needed. This fakes it.
+ bb.append("_id", 0);
+ bb.append("$noFieldsNeeded", 1);
+ return bb.obj();
+ }
- bool needId = false;
- string last;
- for (set<string>::const_iterator it(fields.begin()), end(fields.end()); it!=end; ++it) {
- if (str::startsWith(*it, "_id") && (it->size() == 3 || (*it)[3] == '.')) {
- // _id and subfields are handled specially due in part to SERVER-7502
- needId = true;
- continue;
- }
-
- 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, due to SERVER-6527 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 + '.';
- bb.append(*it, 1);
+ bool needId = false;
+ string last;
+ for (set<string>::const_iterator it(fields.begin()), end(fields.end()); it != end; ++it) {
+ if (str::startsWith(*it, "_id") && (it->size() == 3 || (*it)[3] == '.')) {
+ // _id and subfields are handled specially due in part to SERVER-7502
+ needId = true;
+ continue;
}
- if (needId) // we are explicit either way
- bb.append("_id", 1);
- else
- bb.append("_id", 0);
+ 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, due to SERVER-6527 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;
+ }
- return bb.obj();
+ last = *it + '.';
+ bb.append(*it, 1);
}
- // 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 (needId) // we are explicit either way
+ bb.append("_id", 1);
+ else
+ bb.append("_id", 0);
- if (needWholeDocument || needTextScore) {
- // can't use ParsedDeps in this case
- return boost::none;
- }
+ return bb.obj();
+}
- 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));
- }
+// 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;
+ }
- return ParsedDeps(md.freeze());
+ 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());
+}
+
namespace {
- // Mutually recursive with arrayHelper
- Document documentHelper(const BSONObj& bson, const Document& neededFields);
-
- // Handles array-typed values for ParsedDeps::extractFields
- Value arrayHelper(const BSONObj& bson, const Document& neededFields) {
- BSONObjIterator it(bson);
-
- vector<Value> values;
- while (it.more()) {
- BSONElement bsonElement(it.next());
- if (bsonElement.type() == Object) {
- Document sub = documentHelper(bsonElement.embeddedObject(), neededFields);
- values.push_back(Value(sub));
- }
-
- if (bsonElement.type() == Array) {
- values.push_back(arrayHelper(bsonElement.embeddedObject(), neededFields));
- }
+// Mutually recursive with arrayHelper
+Document documentHelper(const BSONObj& bson, const Document& neededFields);
+
+// Handles array-typed values for ParsedDeps::extractFields
+Value arrayHelper(const BSONObj& bson, const Document& neededFields) {
+ BSONObjIterator it(bson);
+
+ vector<Value> values;
+ while (it.more()) {
+ BSONElement bsonElement(it.next());
+ if (bsonElement.type() == Object) {
+ Document sub = documentHelper(bsonElement.embeddedObject(), neededFields);
+ values.push_back(Value(sub));
}
- return Value(std::move(values));
+ if (bsonElement.type() == Array) {
+ values.push_back(arrayHelper(bsonElement.embeddedObject(), neededFields));
+ }
}
- // Handles object-typed values including the top-level for ParsedDeps::extractFields
- Document documentHelper(const BSONObj& bson, const Document& neededFields) {
- MutableDocument md(neededFields.size());
+ return Value(std::move(values));
+}
- BSONObjIterator it(bson);
- while (it.more()) {
- BSONElement bsonElement (it.next());
- StringData fieldName = bsonElement.fieldNameStringData();
- Value isNeeded = neededFields[fieldName];
+// Handles object-typed values including the top-level for ParsedDeps::extractFields
+Document documentHelper(const BSONObj& bson, const Document& neededFields) {
+ MutableDocument md(neededFields.size());
- if (isNeeded.missing())
- continue;
+ BSONObjIterator it(bson);
+ while (it.more()) {
+ BSONElement bsonElement(it.next());
+ StringData fieldName = bsonElement.fieldNameStringData();
+ Value isNeeded = neededFields[fieldName];
- if (isNeeded.getType() == Bool) {
- md.addField(fieldName, Value(bsonElement));
- continue;
- }
+ if (isNeeded.missing())
+ continue;
- dassert(isNeeded.getType() == Object);
+ if (isNeeded.getType() == Bool) {
+ md.addField(fieldName, Value(bsonElement));
+ continue;
+ }
- if (bsonElement.type() == Object) {
- Document sub = documentHelper(bsonElement.embeddedObject(), isNeeded.getDocument());
- md.addField(fieldName, Value(sub));
- }
+ dassert(isNeeded.getType() == Object);
- if (bsonElement.type() == Array) {
- md.addField(fieldName, arrayHelper(bsonElement.embeddedObject(),
- isNeeded.getDocument()));
- }
+ if (bsonElement.type() == Object) {
+ Document sub = documentHelper(bsonElement.embeddedObject(), isNeeded.getDocument());
+ md.addField(fieldName, Value(sub));
}
- return md.freeze();
+ if (bsonElement.type() == Array) {
+ md.addField(fieldName,
+ arrayHelper(bsonElement.embeddedObject(), isNeeded.getDocument()));
+ }
}
-} // namespace
- Document ParsedDeps::extractFields(const BSONObj& input) const {
- return documentHelper(input, _fields);
- }
+ return md.freeze();
+}
+} // namespace
+
+Document ParsedDeps::extractFields(const BSONObj& input) const {
+ return documentHelper(input, _fields);
+}
}