summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline')
-rw-r--r--src/mongo/db/pipeline/dependencies.cpp229
-rw-r--r--src/mongo/db/pipeline/dependencies.h114
-rw-r--r--src/mongo/db/pipeline/dependencies_test.cpp76
-rw-r--r--src/mongo/db/pipeline/document_source_add_fields_test.cpp4
-rw-r--r--src/mongo/db/pipeline/document_source_bucket_auto_test.cpp10
-rw-r--r--src/mongo/db/pipeline/document_source_cursor.cpp14
-rw-r--r--src/mongo/db/pipeline/document_source_cursor.h24
-rw-r--r--src/mongo/db/pipeline/document_source_facet.cpp10
-rw-r--r--src/mongo/db/pipeline/document_source_facet_test.cpp22
-rw-r--r--src/mongo/db/pipeline/document_source_geo_near.cpp4
-rw-r--r--src/mongo/db/pipeline/document_source_geo_near_cursor.cpp8
-rw-r--r--src/mongo/db/pipeline/document_source_geo_near_cursor.h2
-rw-r--r--src/mongo/db/pipeline/document_source_group_test.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_limit_test.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_lookup.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_match.cpp7
-rw-r--r--src/mongo/db/pipeline/document_source_match_test.cpp44
-rw-r--r--src/mongo/db/pipeline/document_source_project_test.cpp8
-rw-r--r--src/mongo/db/pipeline/document_source_replace_root_test.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_sequential_document_cache.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_sort.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_sort_test.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_unwind_test.cpp2
-rw-r--r--src/mongo/db/pipeline/expression.cpp17
-rw-r--r--src/mongo/db/pipeline/expression_test.cpp8
-rw-r--r--src/mongo/db/pipeline/field_path.cpp13
-rw-r--r--src/mongo/db/pipeline/parsed_exclusion_projection_test.cpp2
-rw-r--r--src/mongo/db/pipeline/pipeline.cpp12
-rw-r--r--src/mongo/db/pipeline/pipeline.h2
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp75
-rw-r--r--src/mongo/db/pipeline/pipeline_d.h3
-rw-r--r--src/mongo/db/pipeline/pipeline_test.cpp43
32 files changed, 259 insertions, 508 deletions
diff --git a/src/mongo/db/pipeline/dependencies.cpp b/src/mongo/db/pipeline/dependencies.cpp
index c9482c9f0e1..7bc9532ed6f 100644
--- a/src/mongo/db/pipeline/dependencies.cpp
+++ b/src/mongo/db/pipeline/dependencies.cpp
@@ -29,6 +29,7 @@
#include "mongo/platform/basic.h"
+#include "mongo/db/exec/document_value/document_metadata_fields.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/pipeline/dependencies.h"
#include "mongo/db/pipeline/field_path.h"
@@ -36,50 +37,17 @@
namespace mongo {
-constexpr DepsTracker::MetadataAvailable DepsTracker::kAllGeoNearDataAvailable;
-
-bool DepsTracker::_appendMetaProjections(BSONObjBuilder* projectionBuilder) const {
- if (_needTextScore) {
- projectionBuilder->append(Document::metaFieldTextScore,
- BSON("$meta"
- << "textScore"));
- }
- if (_needSortKey) {
- projectionBuilder->append(Document::metaFieldSortKey,
- BSON("$meta"
- << "sortKey"));
- }
- if (_needGeoNearDistance) {
- projectionBuilder->append(Document::metaFieldGeoNearDistance,
- BSON("$meta"
- << "geoNearDistance"));
- }
- if (_needGeoNearPoint) {
- projectionBuilder->append(Document::metaFieldGeoNearPoint,
- BSON("$meta"
- << "geoNearPoint"));
- }
- return (_needTextScore || _needSortKey || _needGeoNearDistance || _needGeoNearPoint);
-}
-
-BSONObj DepsTracker::toProjection() const {
+BSONObj DepsTracker::toProjectionWithoutMetadata() const {
BSONObjBuilder bb;
- const bool needsMetadata = _appendMetaProjections(&bb);
-
if (needWholeDocument) {
return bb.obj();
}
if (fields.empty()) {
- if (needsMetadata) {
- // We only need metadata, but there is no easy way to express this in the query
- // projection language. We use $noFieldsNeeded with a meta-projection since this is an
- // inclusion projection which will exclude all existing fields but add the metadata.
- bb.append("_id", 0);
- bb.append("$__INTERNAL_QUERY_PROJECTION_RESERVED", 1);
- }
- // We either need nothing (as we would if this was logically a count), or only the metadata.
+ // We need no user-level fields (as we would if this was logically a count). Since there is
+ // no way of expressing a projection that indicates no depencies, we return an empty
+ // projection.
return bb.obj();
}
@@ -103,10 +71,11 @@ BSONObj DepsTracker::toProjection() const {
last = field + '.';
- // We should only have dependencies on fields that are valid in aggregation. Create a
- // FieldPath to check this.
- FieldPath fieldPath(field);
-
+ {
+ // Check that the field requested is a valid field name in the agg language. This
+ // constructor will throw if it isn't.
+ FieldPath fp(field);
+ }
bb.append(field, 1);
}
@@ -118,173 +87,21 @@ BSONObj DepsTracker::toProjection() const {
return bb.obj();
}
-// 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;
+void DepsTracker::setNeedsMetadata(DocumentMetadataFields::MetaType type, bool required) {
+ // For everything but sortKey/randval metadata, check that it's available. A pipeline can
+ // generate those types of metadata.
- if (needWholeDocument || _needTextScore) {
- // can't use ParsedDeps in this case
- return boost::none;
+ if (type != DocumentMetadataFields::MetaType::kSortKey &&
+ type != DocumentMetadataFields::MetaType::kRandVal) {
+ uassert(40218,
+ str::stream() << "pipeline requires " << type
+ << " metadata, but it is not available",
+ !required || isMetadataAvailable(type));
}
- std::string last;
- for (const auto& field : fields) {
- if (!last.empty() && str::startsWith(field, 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 = field + '.';
- md.setNestedField(field, Value(true));
- }
-
- return ParsedDeps(md.freeze());
-}
-
-bool DepsTracker::getNeedsMetadata(MetadataType type) const {
- switch (type) {
- case MetadataType::TEXT_SCORE:
- return _needTextScore;
- case MetadataType::SORT_KEY:
- return _needSortKey;
- case MetadataType::GEO_NEAR_DISTANCE:
- return _needGeoNearDistance;
- case MetadataType::GEO_NEAR_POINT:
- return _needGeoNearPoint;
- }
- MONGO_UNREACHABLE;
-}
-
-bool DepsTracker::isMetadataAvailable(MetadataType type) const {
- switch (type) {
- case MetadataType::TEXT_SCORE:
- return _metadataAvailable & MetadataAvailable::kTextScore;
- case MetadataType::SORT_KEY:
- MONGO_UNREACHABLE;
- case MetadataType::GEO_NEAR_DISTANCE:
- return _metadataAvailable & MetadataAvailable::kGeoNearDistance;
- case MetadataType::GEO_NEAR_POINT:
- return _metadataAvailable & MetadataAvailable::kGeoNearPoint;
- }
- MONGO_UNREACHABLE;
-}
-
-void DepsTracker::setNeedsMetadata(MetadataType type, bool required) {
- switch (type) {
- case MetadataType::TEXT_SCORE:
- uassert(40218,
- "pipeline requires text score metadata, but there is no text score available",
- !required || isMetadataAvailable(type));
- _needTextScore = required;
- return;
- case MetadataType::SORT_KEY:
- invariant(required || !_needSortKey);
- _needSortKey = required;
- return;
- case MetadataType::GEO_NEAR_DISTANCE:
- uassert(50860,
- "pipeline requires $geoNear distance metadata, but it is not available",
- !required || isMetadataAvailable(type));
- invariant(required || !_needGeoNearDistance);
- _needGeoNearDistance = required;
- return;
- case MetadataType::GEO_NEAR_POINT:
- uassert(50859,
- "pipeline requires $geoNear point metadata, but it is not available",
- !required || isMetadataAvailable(type));
- invariant(required || !_needGeoNearPoint);
- _needGeoNearPoint = required;
- return;
- }
- MONGO_UNREACHABLE;
-}
-
-std::vector<DepsTracker::MetadataType> DepsTracker::getAllRequiredMetadataTypes() const {
- std::vector<MetadataType> reqs;
- if (_needTextScore) {
- reqs.push_back(MetadataType::TEXT_SCORE);
- }
- if (_needSortKey) {
- reqs.push_back(MetadataType::SORT_KEY);
- }
- if (_needGeoNearDistance) {
- reqs.push_back(MetadataType::GEO_NEAR_DISTANCE);
- }
- if (_needGeoNearPoint) {
- reqs.push_back(MetadataType::GEO_NEAR_POINT);
- }
- return reqs;
-}
-
-namespace {
-// Mutually recursive with arrayHelper
-Document documentHelper(const BSONObj& bson, const Document& neededFields, int nFieldsNeeded = -1);
-
-// Handles array-typed values for ParsedDeps::extractFields
-Value arrayHelper(const BSONObj& bson, const Document& neededFields) {
- BSONObjIterator it(bson);
-
- std::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));
- }
- }
-
- return Value(std::move(values));
-}
-
-// Handles object-typed values including the top-level for ParsedDeps::extractFields
-Document documentHelper(const BSONObj& bson, const Document& neededFields, int nFieldsNeeded) {
- // We cache the number of top level fields, so don't need to re-compute it every time. For
- // sub-documents, just scan for the number of fields.
- if (nFieldsNeeded == -1) {
- nFieldsNeeded = neededFields.size();
- }
- MutableDocument md(nFieldsNeeded);
-
- BSONObjIterator it(bson);
- while (it.more() && nFieldsNeeded > 0) {
- auto bsonElement = it.next();
- StringData fieldName = bsonElement.fieldNameStringData();
- Value isNeeded = neededFields[fieldName];
-
- if (isNeeded.missing())
- continue;
-
- --nFieldsNeeded; // Found a needed field.
- if (isNeeded.getType() == Bool) {
- md.addField(fieldName, Value(bsonElement));
- } else {
- dassert(isNeeded.getType() == Object);
-
- if (bsonElement.type() == BSONType::Object) {
- md.addField(
- fieldName,
- Value(documentHelper(bsonElement.embeddedObject(), isNeeded.getDocument())));
- } else if (bsonElement.type() == BSONType::Array) {
- md.addField(fieldName,
- arrayHelper(bsonElement.embeddedObject(), isNeeded.getDocument()));
- }
- }
- }
-
- return md.freeze();
-}
-} // namespace
-
-Document ParsedDeps::extractFields(const BSONObj& input) const {
- return documentHelper(input, _fields, _nFields);
+ // If the metadata type is not required, then it should not be recorded as a metadata
+ // dependency.
+ invariant(required || !_metadataDeps[type]);
+ _metadataDeps[type] = required;
}
} // namespace mongo
diff --git a/src/mongo/db/pipeline/dependencies.h b/src/mongo/db/pipeline/dependencies.h
index 27e2efc41fd..eff5610b089 100644
--- a/src/mongo/db/pipeline/dependencies.h
+++ b/src/mongo/db/pipeline/dependencies.h
@@ -37,7 +37,6 @@
#include "mongo/db/pipeline/variables.h"
namespace mongo {
-class ParsedDeps;
/**
* This struct allows components in an agg pipeline to report what they need from their input.
@@ -69,56 +68,40 @@ struct DepsTracker {
};
/**
- * Represents the type of metadata a pipeline might request.
+ * Represents a state where all geo metadata is available.
*/
- enum class MetadataType {
- // The score associated with a text match.
- TEXT_SCORE,
-
- // The key to use for sorting.
- SORT_KEY,
-
- // The computed distance for a near query.
- GEO_NEAR_DISTANCE,
-
- // The point used in the computation of the GEO_NEAR_DISTANCE.
- GEO_NEAR_POINT,
- };
+ static constexpr auto kAllGeoNearData = QueryMetadataBitSet(
+ (1 << DocumentMetadataFields::kGeoNearDist) | (1 << DocumentMetadataFields::kGeoNearPoint));
/**
- * Represents what metadata is available on documents that are input to the pipeline.
+ * Represents a state where all metadata is available.
*/
- enum MetadataAvailable {
- kNoMetadata = 0,
- kTextScore = 1 << 1,
- kGeoNearDistance = 1 << 2,
- kGeoNearPoint = 1 << 3,
- };
+ static constexpr auto kAllMetadata =
+ QueryMetadataBitSet(~(1 << DocumentMetadataFields::kNumFields));
/**
- * Represents a state where all geo metadata is available.
+ * Represents a state where only text score metadata is available.
*/
- static constexpr auto kAllGeoNearDataAvailable =
- MetadataAvailable(MetadataAvailable::kGeoNearDistance | MetadataAvailable::kGeoNearPoint);
+ static constexpr auto kOnlyTextScore =
+ QueryMetadataBitSet(1 << DocumentMetadataFields::kTextScore);
/**
- * Represents a state where all metadata is available.
+ * Represents a state where no metadata is available.
*/
- static constexpr auto kAllMetadataAvailable =
- MetadataAvailable(kTextScore | kGeoNearDistance | kGeoNearPoint);
+ static constexpr auto kNoMetadata = QueryMetadataBitSet();
+
- DepsTracker(MetadataAvailable metadataAvailable = kNoMetadata)
+ DepsTracker(QueryMetadataBitSet metadataAvailable = kNoMetadata)
: _metadataAvailable(metadataAvailable) {}
/**
- * Returns a projection object covering the dependencies tracked by this class.
+ * Returns a projection object covering the non-metadata dependencies tracked by this class, or
+ * empty BSONObj if the entire document is required.
*/
- BSONObj toProjection() const;
-
- boost::optional<ParsedDeps> toParsedDeps() const;
+ BSONObj toProjectionWithoutMetadata() const;
bool hasNoRequirements() const {
- return fields.empty() && !needWholeDocument && !_needTextScore;
+ return fields.empty() && !needWholeDocument && !_metadataDeps.any();
}
/**
@@ -134,7 +117,7 @@ struct DepsTracker {
/**
* Returns a value with bits set indicating the types of metadata available.
*/
- MetadataAvailable getMetadataAvailable() const {
+ QueryMetadataBitSet getMetadataAvailable() const {
return _metadataAvailable;
}
@@ -143,7 +126,9 @@ struct DepsTracker {
* illegal to call this with MetadataType::SORT_KEY, since the sort key will always be available
* if needed.
*/
- bool isMetadataAvailable(MetadataType type) const;
+ bool isMetadataAvailable(DocumentMetadataFields::MetaType type) const {
+ return _metadataAvailable[type];
+ }
/**
* Sets whether or not metadata 'type' is required. Throws if 'required' is true but that
@@ -151,58 +136,49 @@ struct DepsTracker {
*
* Except for MetadataType::SORT_KEY, once 'type' is required, it cannot be unset.
*/
- void setNeedsMetadata(MetadataType type, bool required);
+ void setNeedsMetadata(DocumentMetadataFields::MetaType type, bool required);
/**
* Returns true if the DepsTracker requires that metadata of type 'type' is present.
*/
- bool getNeedsMetadata(MetadataType type) const;
+ bool getNeedsMetadata(DocumentMetadataFields::MetaType type) const {
+ return _metadataDeps[type];
+ }
/**
* Returns true if there exists a type of metadata required by the DepsTracker.
*/
bool getNeedsAnyMetadata() const {
- return _needTextScore || _needSortKey || _needGeoNearDistance || _needGeoNearPoint;
+ return _metadataDeps.any();
}
/**
- * Returns a vector containing all the types of metadata required by this DepsTracker.
+ * Return all of the metadata dependencies.
*/
- std::vector<MetadataType> getAllRequiredMetadataTypes() const;
-
- std::set<std::string> fields; // Names of needed fields in dotted notation.
- std::set<Variables::Id> vars; // IDs of referenced variables.
- bool needWholeDocument = false; // If true, ignore 'fields'; the whole document is needed.
+ QueryMetadataBitSet& metadataDeps() {
+ return _metadataDeps;
+ }
+ const QueryMetadataBitSet& metadataDeps() const {
+ return _metadataDeps;
+ }
-private:
/**
- * Appends the meta projections for the sort key and/or text score to 'bb' if necessary. Returns
- * true if either type of metadata was needed, and false otherwise.
+ * Request that all metadata in the given QueryMetadataBitSet be added as dependencies.
*/
- bool _appendMetaProjections(BSONObjBuilder* bb) const;
-
- MetadataAvailable _metadataAvailable;
-
- // Each member variable influences a different $meta projection.
- bool _needTextScore = false; // {$meta: "textScore"}
- bool _needSortKey = false; // {$meta: "sortKey"}
- bool _needGeoNearDistance = false; // {$meta: "geoNearDistance"}
- bool _needGeoNearPoint = false; // {$meta: "geoNearPoint"}
-};
+ void requestMetadata(const QueryMetadataBitSet& metadata) {
+ _metadataDeps |= metadata;
+ }
-/**
- * This class is designed to quickly extract the needed fields from a BSONObj into a Document.
- * It should only be created by a call to DepsTracker::ParsedDeps
- */
-class ParsedDeps {
-public:
- Document extractFields(const BSONObj& input) const;
+ std::set<std::string> fields; // Names of needed fields in dotted notation.
+ std::set<Variables::Id> vars; // IDs of referenced variables.
+ bool needWholeDocument = false; // If true, ignore 'fields'; the whole document is needed.
private:
- friend struct DepsTracker; // so it can call constructor
- explicit ParsedDeps(Document&& fields) : _fields(std::move(fields)), _nFields(_fields.size()) {}
+ // Represents all metadata available to the pipeline.
+ QueryMetadataBitSet _metadataAvailable;
- Document _fields;
- int _nFields; // Cache the number of top-level fields needed.
+ // Represents which metadata is used by the pipeline. This is populated while performing
+ // dependency analysis.
+ QueryMetadataBitSet _metadataDeps;
};
} // namespace mongo
diff --git a/src/mongo/db/pipeline/dependencies_test.cpp b/src/mongo/db/pipeline/dependencies_test.cpp
index de11708289d..f5b9c5a37a5 100644
--- a/src/mongo/db/pipeline/dependencies_test.cpp
+++ b/src/mongo/db/pipeline/dependencies_test.cpp
@@ -44,9 +44,6 @@ namespace {
using std::set;
using std::string;
-static const BSONObj metaTextScore = BSON("$meta"
- << "textScore");
-
template <size_t ArrayLen>
set<string> arrayToSet(const char* (&array)[ArrayLen]) {
set<string> out;
@@ -55,53 +52,64 @@ set<string> arrayToSet(const char* (&array)[ArrayLen]) {
return out;
}
+TEST(DependenciesTest, CheckClassConstants) {
+ ASSERT_TRUE(DepsTracker::kAllGeoNearData[DocumentMetadataFields::kGeoNearPoint]);
+ ASSERT_TRUE(DepsTracker::kAllGeoNearData[DocumentMetadataFields::kGeoNearDist]);
+ ASSERT_EQ(DepsTracker::kAllGeoNearData.count(), 2);
+ ASSERT_TRUE(DepsTracker::kAllMetadata.all());
+ ASSERT_EQ(DepsTracker::kOnlyTextScore.count(), 1);
+ ASSERT_TRUE(DepsTracker::kOnlyTextScore[DocumentMetadataFields::kTextScore]);
+}
+
TEST(DependenciesToProjectionTest, ShouldIncludeAllFieldsAndExcludeIdIfNotSpecified) {
const char* array[] = {"a", "b"};
DepsTracker deps;
deps.fields = arrayToSet(array);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "b" << 1 << "_id" << 0));
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSON("a" << 1 << "b" << 1 << "_id" << 0));
}
TEST(DependenciesToProjectionTest, ShouldIncludeFieldEvenIfSuffixOfAnotherIncludedField) {
const char* array[] = {"a", "ab"};
DepsTracker deps;
deps.fields = arrayToSet(array);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "ab" << 1 << "_id" << 0));
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(),
+ BSON("a" << 1 << "ab" << 1 << "_id" << 0));
}
TEST(DependenciesToProjectionTest, ShouldNotIncludeSubFieldIfTopLevelAlreadyIncluded) {
const char* array[] = {"a", "b", "a.b"}; // a.b included by a
DepsTracker deps;
deps.fields = arrayToSet(array);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "b" << 1 << "_id" << 0));
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSON("a" << 1 << "b" << 1 << "_id" << 0));
}
TEST(DependenciesToProjectionTest, ShouldIncludeIdIfNeeded) {
const char* array[] = {"a", "_id"};
DepsTracker deps;
deps.fields = arrayToSet(array);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "_id" << 1));
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSON("a" << 1 << "_id" << 1));
}
TEST(DependenciesToProjectionTest, ShouldIncludeEntireIdEvenIfOnlyASubFieldIsNeeded) {
const char* array[] = {"a", "_id.a"}; // still include whole _id (SERVER-7502)
DepsTracker deps;
deps.fields = arrayToSet(array);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "_id" << 1));
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSON("a" << 1 << "_id" << 1));
}
TEST(DependenciesToProjectionTest, ShouldNotIncludeSubFieldOfIdIfIdIncluded) {
const char* array[] = {"a", "_id", "_id.a"}; // handle both _id and subfield
DepsTracker deps;
deps.fields = arrayToSet(array);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("a" << 1 << "_id" << 1));
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSON("a" << 1 << "_id" << 1));
}
TEST(DependenciesToProjectionTest, ShouldIncludeFieldPrefixedById) {
const char* array[] = {"a", "_id", "_id_a"}; // _id prefixed but non-subfield
DepsTracker deps;
deps.fields = arrayToSet(array);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON("_id_a" << 1 << "a" << 1 << "_id" << 1));
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(),
+ BSON("_id_a" << 1 << "a" << 1 << "_id" << 1));
}
TEST(DependenciesToProjectionTest, ShouldOutputEmptyObjectIfEntireDocumentNeeded) {
@@ -109,55 +117,59 @@ TEST(DependenciesToProjectionTest, ShouldOutputEmptyObjectIfEntireDocumentNeeded
DepsTracker deps;
deps.fields = arrayToSet(array);
deps.needWholeDocument = true;
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSONObj());
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSONObj());
}
TEST(DependenciesToProjectionTest, ShouldOnlyRequestTextScoreIfEntireDocumentAndTextScoreNeeded) {
const char* array[] = {"a"}; // needTextScore with needWholeDocument
- DepsTracker deps(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker deps(DepsTracker::kOnlyTextScore);
deps.fields = arrayToSet(array);
deps.needWholeDocument = true;
- deps.setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON(Document::metaFieldTextScore << metaTextScore));
+ deps.setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSONObj());
+ ASSERT_EQ(deps.metadataDeps().count(), 1u);
+ ASSERT_TRUE(deps.metadataDeps()[DocumentMetadataFields::kTextScore]);
}
TEST(DependenciesToProjectionTest,
ShouldRequireFieldsAndTextScoreIfTextScoreNeededWithoutWholeDocument) {
const char* array[] = {"a"}; // needTextScore without needWholeDocument
- DepsTracker deps(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker deps(DepsTracker::kOnlyTextScore);
deps.fields = arrayToSet(array);
- deps.setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
- ASSERT_BSONOBJ_EQ(
- deps.toProjection(),
- BSON(Document::metaFieldTextScore << metaTextScore << "a" << 1 << "_id" << 0));
+ deps.setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSON("a" << 1 << "_id" << 0));
+ ASSERT_EQ(deps.metadataDeps().count(), 1u);
+ ASSERT_TRUE(deps.metadataDeps()[DocumentMetadataFields::kTextScore]);
}
TEST(DependenciesToProjectionTest, ShouldProduceEmptyObjectIfThereAreNoDependencies) {
- DepsTracker deps(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker deps(DepsTracker::kOnlyTextScore);
deps.fields = {};
deps.needWholeDocument = false;
- deps.setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, false);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSONObj());
+ deps.setNeedsMetadata(DocumentMetadataFields::kTextScore, false);
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSONObj());
}
-TEST(DependenciesToProjectionTest, ShouldAttemptToExcludeOtherFieldsIfOnlyTextScoreIsNeeded) {
- DepsTracker deps(DepsTracker::MetadataAvailable::kTextScore);
+TEST(DependenciesToProjectionTest, ShouldReturnEmptyObjectIfOnlyTextScoreIsNeeded) {
+ DepsTracker deps(DepsTracker::kOnlyTextScore);
deps.fields = {};
deps.needWholeDocument = false;
- deps.setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
- ASSERT_BSONOBJ_EQ(deps.toProjection(),
- BSON(Document::metaFieldTextScore << metaTextScore << "_id" << 0
- << "$__INTERNAL_QUERY_PROJECTION_RESERVED"
- << 1));
+ deps.setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSONObj());
+
+ ASSERT_EQ(deps.metadataDeps().count(), 1u);
+ ASSERT_TRUE(deps.metadataDeps()[DocumentMetadataFields::kTextScore]);
}
TEST(DependenciesToProjectionTest,
ShouldRequireTextScoreIfNoFieldsPresentButWholeDocumentIsNeeded) {
- DepsTracker deps(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker deps(DepsTracker::kOnlyTextScore);
deps.fields = {};
deps.needWholeDocument = true;
- deps.setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
- ASSERT_BSONOBJ_EQ(deps.toProjection(), BSON(Document::metaFieldTextScore << metaTextScore));
+ deps.setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
+ ASSERT_BSONOBJ_EQ(deps.toProjectionWithoutMetadata(), BSONObj());
+ ASSERT_EQ(deps.metadataDeps().count(), 1u);
+ ASSERT_TRUE(deps.metadataDeps()[DocumentMetadataFields::kTextScore]);
}
} // namespace
diff --git a/src/mongo/db/pipeline/document_source_add_fields_test.cpp b/src/mongo/db/pipeline/document_source_add_fields_test.cpp
index da57f5f7847..e20820feb0d 100644
--- a/src/mongo/db/pipeline/document_source_add_fields_test.cpp
+++ b/src/mongo/db/pipeline/document_source_add_fields_test.cpp
@@ -147,7 +147,7 @@ TEST_F(AddFieldsTest, ShouldAddReferencedFieldsToDependencies) {
auto addFields = DocumentSourceAddFields::create(
fromjson("{a: true, x: '$b', y: {$and: ['$c','$d']}, z: {$meta: 'textScore'}}"),
getExpCtx());
- DepsTracker dependencies(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker dependencies(DepsTracker::kOnlyTextScore);
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, addFields->getDependencies(&dependencies));
ASSERT_EQUALS(3U, dependencies.fields.size());
@@ -164,7 +164,7 @@ TEST_F(AddFieldsTest, ShouldAddReferencedFieldsToDependencies) {
ASSERT_EQUALS(1U, dependencies.fields.count("c"));
ASSERT_EQUALS(1U, dependencies.fields.count("d"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(AddFieldsTest, ShouldPropagatePauses) {
diff --git a/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp b/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp
index 5f450c1f792..9c68c05a50c 100644
--- a/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp
+++ b/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp
@@ -450,19 +450,19 @@ TEST_F(BucketAutoTests, ShouldAddDependenciesOfGroupByFieldAndComputedFields) {
ASSERT_EQUALS(1U, dependencies.fields.count("b"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(BucketAutoTests, ShouldNeedTextScoreInDependenciesFromGroupByField) {
auto bucketAuto =
createBucketAuto(fromjson("{$bucketAuto : {groupBy : {$meta: 'textScore'}, buckets : 2}}"));
- DepsTracker dependencies(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker dependencies(DepsTracker::kOnlyTextScore);
ASSERT_EQUALS(DepsTracker::State::EXHAUSTIVE_ALL, bucketAuto->getDependencies(&dependencies));
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(BucketAutoTests, ShouldNeedTextScoreInDependenciesFromOutputField) {
@@ -470,7 +470,7 @@ TEST_F(BucketAutoTests, ShouldNeedTextScoreInDependenciesFromOutputField) {
createBucketAuto(fromjson("{$bucketAuto : {groupBy : '$x', buckets : 2, output: {avg : "
"{$avg : {$meta : 'textScore'}}}}}"));
- DepsTracker dependencies(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker dependencies(DepsTracker::kOnlyTextScore);
ASSERT_EQUALS(DepsTracker::State::EXHAUSTIVE_ALL, bucketAuto->getDependencies(&dependencies));
ASSERT_EQUALS(1U, dependencies.fields.size());
@@ -478,7 +478,7 @@ TEST_F(BucketAutoTests, ShouldNeedTextScoreInDependenciesFromOutputField) {
ASSERT_EQUALS(1U, dependencies.fields.count("x"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(BucketAutoTests, SerializesDefaultAccumulatorIfOutputFieldIsNotSpecified) {
diff --git a/src/mongo/db/pipeline/document_source_cursor.cpp b/src/mongo/db/pipeline/document_source_cursor.cpp
index eb01db2a2ad..e1193e33cb8 100644
--- a/src/mongo/db/pipeline/document_source_cursor.cpp
+++ b/src/mongo/db/pipeline/document_source_cursor.cpp
@@ -73,13 +73,6 @@ DocumentSource::GetNextResult DocumentSourceCursor::doGetNext() {
return std::move(out);
}
-Document DocumentSourceCursor::transformBSONObjToDocument(const BSONObj& obj) const {
- // Aggregation assumes ownership of underlying BSON.
- return _dependencies ? _dependencies->extractFields(obj)
- : (_inputHasMetadata ? Document::fromBsonWithMetaData(obj.getOwned())
- : Document(obj.getOwned()));
-}
-
void DocumentSourceCursor::loadBatch() {
if (!_exec || _exec->isDisposed()) {
// No more documents.
@@ -92,7 +85,7 @@ void DocumentSourceCursor::loadBatch() {
}
PlanExecutor::ExecState state;
- BSONObj resultObj;
+ Document resultObj;
{
AutoGetCollectionForRead autoColl(pExpCtx->opCtx, _exec->nss());
uassertStatusOK(repl::ReplicationCoordinator::get(pExpCtx->opCtx)
@@ -108,7 +101,7 @@ void DocumentSourceCursor::loadBatch() {
if (_shouldProduceEmptyDocs) {
_currentBatch.push_back(Document());
} else {
- _currentBatch.push_back(transformBSONObjToDocument(resultObj));
+ _currentBatch.push_back(transformDoc(resultObj.getOwned()));
}
if (_limit) {
@@ -228,9 +221,6 @@ Value DocumentSourceCursor::serialize(boost::optional<ExplainOptions::Verbosity>
if (_limit)
out["limit"] = Value(_limit->getLimit());
- if (!_projection.isEmpty())
- out["fields"] = Value(_projection);
-
BSONObjBuilder explainStatsBuilder;
{
diff --git a/src/mongo/db/pipeline/document_source_cursor.h b/src/mongo/db/pipeline/document_source_cursor.h
index fa28dd114a0..60495193b93 100644
--- a/src/mongo/db/pipeline/document_source_cursor.h
+++ b/src/mongo/db/pipeline/document_source_cursor.h
@@ -115,21 +115,6 @@ public:
}
/**
- * Informs this object of projection and dependency information.
- *
- * @param projection The projection that has been passed down to the query system.
- * @param deps The output of DepsTracker::toParsedDeps.
- * @param inputHasMetadata Indicates whether the input BSON object contains metadata fields.
- */
- void setProjection(const BSONObj& projection,
- const boost::optional<ParsedDeps>& deps,
- bool inputHasMetadata) {
- _projection = projection;
- _dependencies = deps;
- _inputHasMetadata = inputHasMetadata;
- }
-
- /**
* Returns the limit associated with this cursor, or -1 if there is no limit.
*/
long long getLimit() const {
@@ -182,9 +167,11 @@ protected:
* If '_shouldProduceEmptyDocs' is false, this function hook is called on each 'obj' returned by
* '_exec' when loading a batch and returns a Document to be added to '_currentBatch'.
*
- * The default implementation is a dependency-aware BSONObj-to-Document transformation.
+ * The default implementation is the identity function.
*/
- virtual Document transformBSONObjToDocument(const BSONObj& obj) const;
+ virtual Document transformDoc(Document&& doc) const {
+ return std::move(doc);
+ }
private:
/**
@@ -213,10 +200,7 @@ private:
// BSONObj members must outlive _projection and cursor.
BSONObj _query;
BSONObj _sort;
- BSONObj _projection;
bool _shouldProduceEmptyDocs = false;
- bool _inputHasMetadata = false;
- boost::optional<ParsedDeps> _dependencies;
boost::intrusive_ptr<DocumentSourceLimit> _limit;
long long _docsAddedToBatches; // for _limit enforcement
diff --git a/src/mongo/db/pipeline/document_source_facet.cpp b/src/mongo/db/pipeline/document_source_facet.cpp
index 34bd1d9a4bd..71e9571f869 100644
--- a/src/mongo/db/pipeline/document_source_facet.cpp
+++ b/src/mongo/db/pipeline/document_source_facet.cpp
@@ -305,14 +305,14 @@ DepsTracker::State DocumentSourceFacet::getDependencies(DepsTracker* deps) const
// The text score is the only type of metadata that could be needed by $facet.
deps->setNeedsMetadata(
- DepsTracker::MetadataType::TEXT_SCORE,
- deps->getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE) ||
- subDepsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ DocumentMetadataFields::kTextScore,
+ deps->getNeedsMetadata(DocumentMetadataFields::kTextScore) ||
+ subDepsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
// If there are variables defined at this stage's scope, there may be dependencies upon
// them in subsequent pipelines. Keep enumerating.
- if (deps->needWholeDocument &&
- deps->getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE) && !scopeHasVariables) {
+ if (deps->needWholeDocument && deps->getNeedsMetadata(DocumentMetadataFields::kTextScore) &&
+ !scopeHasVariables) {
break;
}
}
diff --git a/src/mongo/db/pipeline/document_source_facet_test.cpp b/src/mongo/db/pipeline/document_source_facet_test.cpp
index 5d094fe5bcf..980786689a8 100644
--- a/src/mongo/db/pipeline/document_source_facet_test.cpp
+++ b/src/mongo/db/pipeline/document_source_facet_test.cpp
@@ -618,8 +618,7 @@ TEST_F(DocumentSourceFacetTest, ShouldUnionDependenciesOfInnerPipelines) {
auto needsA = DocumentSourceNeedsA::create();
auto firstPipeline = unittest::assertGet(Pipeline::createFacetPipeline({needsA}, ctx));
- auto firstPipelineDeps =
- firstPipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto firstPipelineDeps = firstPipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_FALSE(firstPipelineDeps.needWholeDocument);
ASSERT_EQ(firstPipelineDeps.fields.size(), 1UL);
ASSERT_EQ(firstPipelineDeps.fields.count("a"), 1UL);
@@ -627,8 +626,7 @@ TEST_F(DocumentSourceFacetTest, ShouldUnionDependenciesOfInnerPipelines) {
auto needsB = DocumentSourceNeedsB::create();
auto secondPipeline = unittest::assertGet(Pipeline::createFacetPipeline({needsB}, ctx));
- auto secondPipelineDeps =
- secondPipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto secondPipelineDeps = secondPipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_FALSE(secondPipelineDeps.needWholeDocument);
ASSERT_EQ(secondPipelineDeps.fields.size(), 1UL);
ASSERT_EQ(secondPipelineDeps.fields.count("b"), 1UL);
@@ -638,10 +636,10 @@ TEST_F(DocumentSourceFacetTest, ShouldUnionDependenciesOfInnerPipelines) {
facets.emplace_back("needsB", std::move(secondPipeline));
auto facetStage = DocumentSourceFacet::create(std::move(facets), ctx);
- DepsTracker deps(DepsTracker::MetadataAvailable::kNoMetadata);
+ DepsTracker deps(DepsTracker::kNoMetadata);
ASSERT_EQ(facetStage->getDependencies(&deps), DepsTracker::State::EXHAUSTIVE_ALL);
ASSERT_FALSE(deps.needWholeDocument);
- ASSERT_FALSE(deps.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_FALSE(deps.getNeedsMetadata(DocumentMetadataFields::kTextScore));
ASSERT_EQ(deps.fields.size(), 2UL);
ASSERT_EQ(deps.fields.count("a"), 1UL);
ASSERT_EQ(deps.fields.count("b"), 1UL);
@@ -676,10 +674,10 @@ TEST_F(DocumentSourceFacetTest, ShouldRequireWholeDocumentIfAnyPipelineRequiresW
facets.emplace_back("needsWholeDocument", std::move(secondPipeline));
auto facetStage = DocumentSourceFacet::create(std::move(facets), ctx);
- DepsTracker deps(DepsTracker::MetadataAvailable::kNoMetadata);
+ DepsTracker deps(DepsTracker::kNoMetadata);
ASSERT_EQ(facetStage->getDependencies(&deps), DepsTracker::State::EXHAUSTIVE_ALL);
ASSERT_TRUE(deps.needWholeDocument);
- ASSERT_FALSE(deps.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_FALSE(deps.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
/**
@@ -688,7 +686,7 @@ TEST_F(DocumentSourceFacetTest, ShouldRequireWholeDocumentIfAnyPipelineRequiresW
class DocumentSourceNeedsOnlyTextScore : public DocumentSourcePassthrough {
public:
DepsTracker::State getDependencies(DepsTracker* deps) const override {
- deps->setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
+ deps->setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
return DepsTracker::State::EXHAUSTIVE_ALL;
}
static boost::intrusive_ptr<DocumentSourceNeedsOnlyTextScore> create() {
@@ -715,10 +713,10 @@ TEST_F(DocumentSourceFacetTest, ShouldRequireTextScoreIfAnyPipelineRequiresTextS
facets.emplace_back("needsTextScore", std::move(thirdPipeline));
auto facetStage = DocumentSourceFacet::create(std::move(facets), ctx);
- DepsTracker deps(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker deps(DepsTracker::kOnlyTextScore);
ASSERT_EQ(facetStage->getDependencies(&deps), DepsTracker::State::EXHAUSTIVE_ALL);
ASSERT_TRUE(deps.needWholeDocument);
- ASSERT_TRUE(deps.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_TRUE(deps.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceFacetTest, ShouldThrowIfAnyPipelineRequiresTextScoreButItIsNotAvailable) {
@@ -735,7 +733,7 @@ TEST_F(DocumentSourceFacetTest, ShouldThrowIfAnyPipelineRequiresTextScoreButItIs
facets.emplace_back("needsTextScore", std::move(secondPipeline));
auto facetStage = DocumentSourceFacet::create(std::move(facets), ctx);
- DepsTracker deps(DepsTracker::MetadataAvailable::kNoMetadata);
+ DepsTracker deps(DepsTracker::kNoMetadata);
ASSERT_THROWS(facetStage->getDependencies(&deps), AssertionException);
}
diff --git a/src/mongo/db/pipeline/document_source_geo_near.cpp b/src/mongo/db/pipeline/document_source_geo_near.cpp
index 61f04889ffa..5081865eeba 100644
--- a/src/mongo/db/pipeline/document_source_geo_near.cpp
+++ b/src/mongo/db/pipeline/document_source_geo_near.cpp
@@ -225,8 +225,8 @@ DepsTracker::State DocumentSourceGeoNear::getDependencies(DepsTracker* deps) con
// produced by this stage, and we could inform the query system that it need not include it in
// its response. For now, assume that we require the entire document as well as the appropriate
// geoNear metadata.
- deps->setNeedsMetadata(DepsTracker::MetadataType::GEO_NEAR_DISTANCE, true);
- deps->setNeedsMetadata(DepsTracker::MetadataType::GEO_NEAR_POINT, needsGeoNearPoint());
+ deps->setNeedsMetadata(DocumentMetadataFields::kGeoNearDist, true);
+ deps->setNeedsMetadata(DocumentMetadataFields::kGeoNearPoint, needsGeoNearPoint());
deps->needWholeDocument = true;
return DepsTracker::State::EXHAUSTIVE_FIELDS;
diff --git a/src/mongo/db/pipeline/document_source_geo_near_cursor.cpp b/src/mongo/db/pipeline/document_source_geo_near_cursor.cpp
index 306bc5f6d3e..0eb6fd5b04b 100644
--- a/src/mongo/db/pipeline/document_source_geo_near_cursor.cpp
+++ b/src/mongo/db/pipeline/document_source_geo_near_cursor.cpp
@@ -83,14 +83,14 @@ const char* DocumentSourceGeoNearCursor::getSourceName() const {
return DocumentSourceGeoNearCursor::kStageName.rawData();
}
-Document DocumentSourceGeoNearCursor::transformBSONObjToDocument(const BSONObj& obj) const {
- MutableDocument output(Document::fromBsonWithMetaData(obj));
+Document DocumentSourceGeoNearCursor::transformDoc(Document&& objInput) const {
+ MutableDocument output(std::move(objInput));
// Scale the distance by the requested factor.
invariant(output.peek().metadata().hasGeoNearDistance(),
str::stream()
<< "Query returned a document that is unexpectedly missing the geoNear distance: "
- << obj.jsonString());
+ << output.peek().toString());
const auto distance = output.peek().metadata().getGeoNearDistance() * _distanceMultiplier;
output.setNestedField(_distanceField, Value(distance));
@@ -99,7 +99,7 @@ Document DocumentSourceGeoNearCursor::transformBSONObjToDocument(const BSONObj&
output.peek().metadata().hasGeoNearPoint(),
str::stream()
<< "Query returned a document that is unexpectedly missing the geoNear point: "
- << obj.jsonString());
+ << output.peek().toString());
output.setNestedField(*_locationField, output.peek().metadata().getGeoNearPoint());
}
diff --git a/src/mongo/db/pipeline/document_source_geo_near_cursor.h b/src/mongo/db/pipeline/document_source_geo_near_cursor.h
index 5022c716d2e..084e8b76bbe 100644
--- a/src/mongo/db/pipeline/document_source_geo_near_cursor.h
+++ b/src/mongo/db/pipeline/document_source_geo_near_cursor.h
@@ -82,7 +82,7 @@ private:
/**
* Transforms 'obj' into a Document, calculating the distance.
*/
- Document transformBSONObjToDocument(const BSONObj& obj) const final;
+ Document transformDoc(Document&& obj) const override final;
// The output field in which to store the computed distance.
FieldPath _distanceField;
diff --git a/src/mongo/db/pipeline/document_source_group_test.cpp b/src/mongo/db/pipeline/document_source_group_test.cpp
index 5de0e26078a..e2fdfe4f107 100644
--- a/src/mongo/db/pipeline/document_source_group_test.cpp
+++ b/src/mongo/db/pipeline/document_source_group_test.cpp
@@ -813,7 +813,7 @@ public:
ASSERT_EQUALS(1U, dependencies.fields.count("u"));
ASSERT_EQUALS(1U, dependencies.fields.count("v"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
};
diff --git a/src/mongo/db/pipeline/document_source_limit_test.cpp b/src/mongo/db/pipeline/document_source_limit_test.cpp
index 67d4954274c..85ccf9a811c 100644
--- a/src/mongo/db/pipeline/document_source_limit_test.cpp
+++ b/src/mongo/db/pipeline/document_source_limit_test.cpp
@@ -116,7 +116,7 @@ TEST_F(DocumentSourceLimitTest, ShouldNotIntroduceAnyDependencies) {
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, limit->getDependencies(&dependencies));
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceLimitTest, ShouldPropagatePauses) {
diff --git a/src/mongo/db/pipeline/document_source_lookup.cpp b/src/mongo/db/pipeline/document_source_lookup.cpp
index 575d3335ba4..e11a44fcf32 100644
--- a/src/mongo/db/pipeline/document_source_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_lookup.cpp
@@ -731,7 +731,7 @@ DepsTracker::State DocumentSourceLookUp::getDependencies(DepsTracker* deps) cons
// subpipeline for the top-level pipeline. So without knowledge of what metadata is in fact
// available, we "lie" and say that all metadata is available to avoid tripping any
// assertions.
- DepsTracker subDeps(DepsTracker::kAllMetadataAvailable);
+ DepsTracker subDeps(DepsTracker::kAllMetadata);
// Get the subpipeline dependencies. Subpipeline stages may reference both 'let' variables
// declared by this $lookup and variables declared externally.
diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp
index 44697476cf1..494b3535879 100644
--- a/src/mongo/db/pipeline/document_source_match.cpp
+++ b/src/mongo/db/pipeline/document_source_match.cpp
@@ -486,7 +486,7 @@ DepsTracker::State DocumentSourceMatch::getDependencies(DepsTracker* deps) const
// A $text aggregation field should return EXHAUSTIVE_FIELDS, since we don't necessarily
// know what field it will be searching without examining indices.
deps->needWholeDocument = true;
- deps->setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
+ deps->setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
return DepsTracker::State::EXHAUSTIVE_FIELDS;
}
@@ -504,8 +504,9 @@ void DocumentSourceMatch::rebuild(BSONObj filter) {
_expression = uassertStatusOK(MatchExpressionParser::parse(
_predicate, pExpCtx, ExtensionsCallbackNoop(), Pipeline::kAllowedMatcherFeatures));
_isTextQuery = isTextQuery(_predicate);
- _dependencies = DepsTracker(_isTextQuery ? DepsTracker::MetadataAvailable::kTextScore
- : DepsTracker::MetadataAvailable::kNoMetadata);
+ _dependencies =
+ DepsTracker(_isTextQuery ? QueryMetadataBitSet().set(DocumentMetadataFields::kTextScore)
+ : DepsTracker::kNoMetadata);
getDependencies(&_dependencies);
}
diff --git a/src/mongo/db/pipeline/document_source_match_test.cpp b/src/mongo/db/pipeline/document_source_match_test.cpp
index de5eb9cbc46..3d42a81f91d 100644
--- a/src/mongo/db/pipeline/document_source_match_test.cpp
+++ b/src/mongo/db/pipeline/document_source_match_test.cpp
@@ -220,15 +220,15 @@ TEST_F(DocumentSourceMatchTest, ShouldAddDependenciesOfAllBranchesOfOrClause) {
ASSERT_EQUALS(1U, dependencies.fields.count("x.y"));
ASSERT_EQUALS(2U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, TextSearchShouldRequireWholeDocumentAndTextScore) {
auto match = DocumentSourceMatch::create(fromjson("{$text: {$search: 'hello'} }"), getExpCtx());
- DepsTracker dependencies(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker dependencies(DepsTracker::kOnlyTextScore);
ASSERT_EQUALS(DepsTracker::State::EXHAUSTIVE_FIELDS, match->getDependencies(&dependencies));
ASSERT_EQUALS(true, dependencies.needWholeDocument);
- ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldOnlyAddOuterFieldAsDependencyOfImplicitEqualityPredicate) {
@@ -239,7 +239,7 @@ TEST_F(DocumentSourceMatchTest, ShouldOnlyAddOuterFieldAsDependencyOfImplicitEqu
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldOnlyAddOuterFieldAsDependencyOfClausesWithinElemMatch) {
@@ -250,7 +250,7 @@ TEST_F(DocumentSourceMatchTest, ShouldOnlyAddOuterFieldAsDependencyOfClausesWith
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest,
@@ -267,7 +267,7 @@ TEST_F(DocumentSourceMatchTest,
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest,
@@ -278,7 +278,7 @@ TEST_F(DocumentSourceMatchTest,
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, match->getDependencies(&dependencies));
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(true, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest,
@@ -289,7 +289,7 @@ TEST_F(DocumentSourceMatchTest,
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, match->getDependencies(&dependencies1));
ASSERT_EQUALS(0U, dependencies1.fields.size());
ASSERT_EQUALS(true, dependencies1.needWholeDocument);
- ASSERT_EQUALS(false, dependencies1.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies1.getNeedsMetadata(DocumentMetadataFields::kTextScore));
query = fromjson("{a: {$_internalSchemaObjectMatch: {$_internalSchemaMaxProperties: 1}}}");
match = DocumentSourceMatch::create(query, getExpCtx());
@@ -298,7 +298,7 @@ TEST_F(DocumentSourceMatchTest,
ASSERT_EQUALS(1U, dependencies2.fields.size());
ASSERT_EQUALS(1U, dependencies2.fields.count("a"));
ASSERT_EQUALS(false, dependencies2.needWholeDocument);
- ASSERT_EQUALS(false, dependencies2.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies2.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest,
@@ -311,7 +311,7 @@ TEST_F(DocumentSourceMatchTest,
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, match->getDependencies(&dependencies));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(true, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest,
@@ -322,7 +322,7 @@ TEST_F(DocumentSourceMatchTest,
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, match->getDependencies(&dependencies));
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(true, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithInternalSchemaType) {
@@ -333,7 +333,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithIntern
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithInternalSchemaCond) {
@@ -346,7 +346,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithIntern
ASSERT_EQUALS(1U, dependencies.fields.count("b"));
ASSERT_EQUALS(1U, dependencies.fields.count("c"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithInternalSchemaXor) {
@@ -359,7 +359,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithIntern
ASSERT_EQUALS(1U, dependencies.fields.count("b"));
ASSERT_EQUALS(1U, dependencies.fields.count("c"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithEmptyJSONSchema) {
@@ -369,7 +369,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithEmptyJ
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, match->getDependencies(&dependencies));
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithJSONSchemaProperties) {
@@ -380,7 +380,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForClausesWithJSONSc
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForMultiplePredicatesWithJSONSchema) {
@@ -392,7 +392,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddCorrectDependenciesForMultiplePredicate
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.count("b"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddOuterFieldToDependenciesIfElemMatchContainsNoFieldNames) {
@@ -403,7 +403,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddOuterFieldToDependenciesIfElemMatchCont
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddNotClausesFieldAsDependency) {
@@ -413,7 +413,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddNotClausesFieldAsDependency) {
ASSERT_EQUALS(1U, dependencies.fields.count("b"));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ShouldAddDependenciesOfEachNorClause) {
@@ -425,7 +425,7 @@ TEST_F(DocumentSourceMatchTest, ShouldAddDependenciesOfEachNorClause) {
ASSERT_EQUALS(1U, dependencies.fields.count("b.c"));
ASSERT_EQUALS(2U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, CommentShouldNotAddAnyDependencies) {
@@ -434,7 +434,7 @@ TEST_F(DocumentSourceMatchTest, CommentShouldNotAddAnyDependencies) {
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, match->getDependencies(&dependencies));
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, ClauseAndedWithCommentShouldAddDependencies) {
@@ -445,7 +445,7 @@ TEST_F(DocumentSourceMatchTest, ClauseAndedWithCommentShouldAddDependencies) {
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceMatchTest, MultipleMatchStagesShouldCombineIntoOne) {
diff --git a/src/mongo/db/pipeline/document_source_project_test.cpp b/src/mongo/db/pipeline/document_source_project_test.cpp
index 9480c80602b..9c04482340e 100644
--- a/src/mongo/db/pipeline/document_source_project_test.cpp
+++ b/src/mongo/db/pipeline/document_source_project_test.cpp
@@ -171,7 +171,7 @@ TEST_F(ProjectStageTest, InclusionShouldAddDependenciesOfIncludedAndComputedFiel
fromjson("{a: true, x: '$b', y: {$and: ['$c','$d']}, z: {$meta: 'textScore'}}"),
getExpCtx(),
"$project"_sd);
- DepsTracker dependencies(DepsTracker::MetadataAvailable::kTextScore);
+ DepsTracker dependencies(DepsTracker::kOnlyTextScore);
ASSERT_EQUALS(DepsTracker::State::EXHAUSTIVE_FIELDS, project->getDependencies(&dependencies));
ASSERT_EQUALS(5U, dependencies.fields.size());
@@ -188,7 +188,7 @@ TEST_F(ProjectStageTest, InclusionShouldAddDependenciesOfIncludedAndComputedFiel
ASSERT_EQUALS(1U, dependencies.fields.count("c"));
ASSERT_EQUALS(1U, dependencies.fields.count("d"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(true, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(ProjectStageTest, ExclusionShouldNotAddDependencies) {
@@ -200,7 +200,7 @@ TEST_F(ProjectStageTest, ExclusionShouldNotAddDependencies) {
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(ProjectStageTest, InclusionProjectionReportsIncludedPathsFromGetModifiedPaths) {
@@ -446,7 +446,7 @@ TEST_F(UnsetTest, UnsetShouldNotAddDependencies) {
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(UnsetTest, UnsetReportsExcludedPathsAsModifiedPaths) {
diff --git a/src/mongo/db/pipeline/document_source_replace_root_test.cpp b/src/mongo/db/pipeline/document_source_replace_root_test.cpp
index 227331d6897..7fac5040d32 100644
--- a/src/mongo/db/pipeline/document_source_replace_root_test.cpp
+++ b/src/mongo/db/pipeline/document_source_replace_root_test.cpp
@@ -272,7 +272,7 @@ TEST_F(ReplaceRootBasics, OnlyDependentFieldIsNewRoot) {
// Should not need any other fields.
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(ReplaceRootBasics, ReplaceRootModifiesAllFields) {
diff --git a/src/mongo/db/pipeline/document_source_sequential_document_cache.cpp b/src/mongo/db/pipeline/document_source_sequential_document_cache.cpp
index 8cdfba006dd..971971ae19b 100644
--- a/src/mongo/db/pipeline/document_source_sequential_document_cache.cpp
+++ b/src/mongo/db/pipeline/document_source_sequential_document_cache.cpp
@@ -115,7 +115,7 @@ Pipeline::SourceContainer::iterator DocumentSourceSequentialDocumentCache::doOpt
// elsewhere. So without knowledge of what metadata is in fact available, here
// we "lie" and say that all metadata is available to avoid tripping any
// assertions.
- DepsTracker deps(DepsTracker::kAllMetadataAvailable);
+ DepsTracker deps(DepsTracker::kAllMetadata);
// Iterate through the pipeline stages until we find one which references an external variable.
for (; prefixSplit != container->end(); ++prefixSplit) {
diff --git a/src/mongo/db/pipeline/document_source_sort.cpp b/src/mongo/db/pipeline/document_source_sort.cpp
index 82b476c791f..d306c4e8248 100644
--- a/src/mongo/db/pipeline/document_source_sort.cpp
+++ b/src/mongo/db/pipeline/document_source_sort.cpp
@@ -158,7 +158,7 @@ DepsTracker::State DocumentSourceSort::getDependencies(DepsTracker* deps) const
}
if (pExpCtx->needsMerge) {
// Include the sort key if we will merge several sorted streams later.
- deps->setNeedsMetadata(DepsTracker::MetadataType::SORT_KEY, true);
+ deps->setNeedsMetadata(DocumentMetadataFields::kSortKey, true);
}
return DepsTracker::State::SEE_NEXT;
diff --git a/src/mongo/db/pipeline/document_source_sort_test.cpp b/src/mongo/db/pipeline/document_source_sort_test.cpp
index 67d909c54d2..88e909d326f 100644
--- a/src/mongo/db/pipeline/document_source_sort_test.cpp
+++ b/src/mongo/db/pipeline/document_source_sort_test.cpp
@@ -173,7 +173,7 @@ TEST_F(DocumentSourceSortTest, Dependencies) {
ASSERT_EQUALS(1U, dependencies.fields.count("a"));
ASSERT_EQUALS(1U, dependencies.fields.count("b.c"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(DocumentSourceSortTest, ReportsNoPathsModified) {
diff --git a/src/mongo/db/pipeline/document_source_unwind_test.cpp b/src/mongo/db/pipeline/document_source_unwind_test.cpp
index 00d0b3390b4..41d76c428b0 100644
--- a/src/mongo/db/pipeline/document_source_unwind_test.cpp
+++ b/src/mongo/db/pipeline/document_source_unwind_test.cpp
@@ -680,7 +680,7 @@ TEST_F(UnwindStageTest, AddsUnwoundPathToDependencies) {
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(1U, dependencies.fields.count("x.y.z"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(UnwindStageTest, ShouldPropagatePauses) {
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp
index 61abc3f009b..6d307929e3e 100644
--- a/src/mongo/db/pipeline/expression.cpp
+++ b/src/mongo/db/pipeline/expression.cpp
@@ -2634,22 +2634,13 @@ Value ExpressionMeta::evaluate(const Document& root, Variables* variables) const
}
void ExpressionMeta::_doAddDependencies(DepsTracker* deps) const {
- if (_metaType == MetaType::kTextScore) {
- deps->setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
-
+ if (_metaType == MetaType::kSearchScore || _metaType == MetaType::kSearchHighlights) {
// We do not add the dependencies for SEARCH_SCORE or SEARCH_HIGHLIGHTS because those values
// are not stored in the collection (or in mongod at all).
- } else if (_metaType == MetaType::kGeoNearDist) {
- deps->setNeedsMetadata(DepsTracker::MetadataType::GEO_NEAR_DISTANCE, true);
- } else if (_metaType == MetaType::kGeoNearPoint) {
- deps->setNeedsMetadata(DepsTracker::MetadataType::GEO_NEAR_POINT, true);
- } else if (_metaType == MetaType::kRecordId) {
- // TODO: SERVER-42560 handle passing of metadata between PlanStage and DS layers.
- } else if (_metaType == MetaType::kIndexKey) {
- // TODO: SERVER-42560 handle passing of metadata between PlanStage and DS layers.
- } else if (_metaType == MetaType::kSortKey) {
- deps->setNeedsMetadata(DepsTracker::MetadataType::SORT_KEY, true);
+ return;
}
+
+ deps->setNeedsMetadata(_metaType, true);
}
/* ----------------------- ExpressionMod ---------------------------- */
diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp
index 0b3b8be1179..859ed6cc22e 100644
--- a/src/mongo/db/pipeline/expression_test.cpp
+++ b/src/mongo/db/pipeline/expression_test.cpp
@@ -262,7 +262,7 @@ protected:
}
ASSERT_BSONOBJ_EQ(expectedDependencies, dependenciesBson.arr());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsAnyMetadata());
}
void assertContents(const intrusive_ptr<Testable>& expr, const BSONArray& expectedContents) {
@@ -1985,7 +1985,7 @@ public:
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(1U, dependencies.fields.count("a.b"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsAnyMetadata());
}
};
@@ -2491,7 +2491,7 @@ public:
expression->addDependencies(&dependencies);
ASSERT_EQUALS(0U, dependencies.fields.size());
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsAnyMetadata());
}
};
@@ -3017,7 +3017,7 @@ public:
ASSERT_EQUALS(1U, dependencies.fields.size());
ASSERT_EQUALS(1U, dependencies.fields.count("a.b"));
ASSERT_EQUALS(false, dependencies.needWholeDocument);
- ASSERT_EQUALS(false, dependencies.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_EQUALS(false, dependencies.getNeedsAnyMetadata());
}
};
diff --git a/src/mongo/db/pipeline/field_path.cpp b/src/mongo/db/pipeline/field_path.cpp
index 2d891ce7b10..6eb9fe46d0b 100644
--- a/src/mongo/db/pipeline/field_path.cpp
+++ b/src/mongo/db/pipeline/field_path.cpp
@@ -47,17 +47,12 @@ const StringDataSet kAllowedDollarPrefixedFields = {
// Metadata fields.
- // TODO SERVER-42560: It may be possible to eliminate some of these, if they're only used for
- // creating the "dependency" projection. Some of them ($dis and $sortKey) may be used in
- // sharded queries and are necessary.
+ // This is necessary for sharded query execution of find() commands. mongos may attach a
+ // $sortKey field to the projection sent to shards so that it can merge the results correctly.
"$sortKey",
- "$pt",
- "$dis",
- "$textScore",
- "$recordId",
- // Used internally for forcing projections to be of a certain type.
- "$__INTERNAL_QUERY_PROJECTION_RESERVED"};
+ // This is necessary for the "showRecordId" feature.
+ "$recordId"};
} // namespace
diff --git a/src/mongo/db/pipeline/parsed_exclusion_projection_test.cpp b/src/mongo/db/pipeline/parsed_exclusion_projection_test.cpp
index 1e1b4b4256e..cc7271be016 100644
--- a/src/mongo/db/pipeline/parsed_exclusion_projection_test.cpp
+++ b/src/mongo/db/pipeline/parsed_exclusion_projection_test.cpp
@@ -149,7 +149,7 @@ TEST(ExclusionProjectionExecutionTest, ShouldNotAddAnyDependencies) {
ASSERT_EQ(deps.fields.size(), 0UL);
ASSERT_FALSE(deps.needWholeDocument);
- ASSERT_FALSE(deps.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_FALSE(deps.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST(ExclusionProjectionExecutionTest, ShouldReportExcludedFieldsAsModified) {
diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp
index 7642b1ef49a..7e9fa39c66d 100644
--- a/src/mongo/db/pipeline/pipeline.cpp
+++ b/src/mongo/db/pipeline/pipeline.cpp
@@ -501,7 +501,7 @@ void Pipeline::addFinalSource(intrusive_ptr<DocumentSource> source) {
_sources.push_back(source);
}
-DepsTracker Pipeline::getDependencies(DepsTracker::MetadataAvailable metadataAvailable) const {
+DepsTracker Pipeline::getDependencies(QueryMetadataBitSet metadataAvailable) const {
DepsTracker deps(metadataAvailable);
const bool scopeHasVariables = pCtx->variablesParseState.hasDefinedVariables();
bool skipFieldsAndMetadataDeps = false;
@@ -533,9 +533,7 @@ DepsTracker Pipeline::getDependencies(DepsTracker::MetadataAvailable metadataAva
}
if (!knowAllMeta) {
- for (auto&& req : localDeps.getAllRequiredMetadataTypes()) {
- deps.setNeedsMetadata(req, true);
- }
+ deps.requestMetadata(localDeps.metadataDeps());
knowAllMeta = status & DepsTracker::State::EXHAUSTIVE_META;
}
@@ -549,15 +547,15 @@ DepsTracker Pipeline::getDependencies(DepsTracker::MetadataAvailable metadataAva
if (!knowAllFields)
deps.needWholeDocument = true; // don't know all fields we need
- if (metadataAvailable & DepsTracker::MetadataAvailable::kTextScore) {
+ if (metadataAvailable[DocumentMetadataFields::kTextScore]) {
// If there is a text score, assume we need to keep it if we can't prove we don't. If we are
// the first half of a pipeline which has been split, future stages might need it.
if (!knowAllMeta) {
- deps.setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
+ deps.setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
}
} else {
// If there is no text score available, then we don't need to ask for it.
- deps.setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, false);
+ deps.setNeedsMetadata(DocumentMetadataFields::kTextScore, false);
}
return deps;
diff --git a/src/mongo/db/pipeline/pipeline.h b/src/mongo/db/pipeline/pipeline.h
index 1af188f4b15..39ba6372687 100644
--- a/src/mongo/db/pipeline/pipeline.h
+++ b/src/mongo/db/pipeline/pipeline.h
@@ -251,7 +251,7 @@ public:
* Returns the dependencies needed by this pipeline. 'metadataAvailable' should reflect what
* metadata is present on documents that are input to the front of the pipeline.
*/
- DepsTracker getDependencies(DepsTracker::MetadataAvailable metadataAvailable) const;
+ DepsTracker getDependencies(QueryMetadataBitSet metadataAvailable) const;
const SourceContainer& getSources() const {
return _sources;
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index c327187ecd3..a523066d2a8 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -193,6 +193,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> attemptToGetExe
const intrusive_ptr<ExpressionContext>& pExpCtx,
BSONObj queryObj,
BSONObj projectionObj,
+ const QueryMetadataBitSet& metadataRequested,
BSONObj sortObj,
boost::optional<std::string> groupIdForDistinctScan,
const AggregationRequest* aggRequest,
@@ -232,6 +233,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> attemptToGetExe
return {cq.getStatus()};
}
+ // Mark the metadata that's requested by the pipeline on the CQ.
+ cq.getValue()->requestAdditionalMetadata(metadataRequested);
+
if (groupIdForDistinctScan) {
// When the pipeline includes a $group that groups by a single field
// (groupIdForDistinctScan), we use getExecutorDistinct() to attempt to get an executor that
@@ -266,13 +270,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> attemptToGetExe
return getExecutorFind(opCtx, collection, std::move(cq.getValue()), permitYield, plannerOpts);
}
-BSONObj removeSortKeyMetaProjection(BSONObj projectionObj) {
- if (!projectionObj[Document::metaFieldSortKey]) {
- return projectionObj;
- }
- return projectionObj.removeField(Document::metaFieldSortKey);
-}
-
/**
* Examines the indexes in 'collection' and returns the field name of a geo-indexed field suitable
* for use in $geoNear. 2d indexes are given priority over 2dsphere indexes.
@@ -366,7 +363,7 @@ PipelineD::buildInnerQueryExecutor(Collection* collection,
// TODO SERVER-37453 this should no longer be necessary when we no don't need locks
// to destroy a PlanExecutor.
- auto deps = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto deps = pipeline->getDependencies(DepsTracker::kNoMetadata);
auto attachExecutorCallback =
[deps](Collection* collection,
std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> exec,
@@ -479,10 +476,10 @@ PipelineD::buildInnerQueryExecutorGeneric(Collection* collection,
// Find the set of fields in the source documents depended on by this pipeline.
DepsTracker deps = pipeline->getDependencies(DocumentSourceMatch::isTextQuery(queryObj)
- ? DepsTracker::MetadataAvailable::kTextScore
- : DepsTracker::MetadataAvailable::kNoMetadata);
+ ? DepsTracker::kOnlyTextScore
+ : DepsTracker::kNoMetadata);
- BSONObj projForQuery = deps.toProjection();
+ BSONObj projForQuery = deps.toProjectionWithoutMetadata();
boost::intrusive_ptr<DocumentSourceSort> sortStage;
boost::intrusive_ptr<DocumentSourceGroup> groupStage;
@@ -536,8 +533,7 @@ PipelineD::buildInnerQueryExecutorGeneric(Collection* collection,
Pipeline* pipeline) {
auto cursor = DocumentSourceCursor::create(
collection, std::move(exec), pipeline->getContext(), trackOplogTS);
- addCursorSource(
- pipeline, std::move(cursor), std::move(deps), queryObj, sortObj, projForQuery);
+ addCursorSource(pipeline, std::move(cursor), std::move(deps), queryObj, sortObj);
};
return std::make_pair(std::move(attachExecutorCallback), std::move(exec));
}
@@ -557,7 +553,7 @@ PipelineD::buildInnerQueryExecutorGeoNear(Collection* collection,
const auto geoNearStage = dynamic_cast<DocumentSourceGeoNear*>(sources.front().get());
invariant(geoNearStage);
- auto deps = pipeline->getDependencies(DepsTracker::kAllGeoNearDataAvailable);
+ auto deps = pipeline->getDependencies(DepsTracker::kAllGeoNearData);
// If the user specified a "key" field, use that field to satisfy the "near" query. Otherwise,
// look for a geo-indexed field in 'collection' that can.
@@ -569,7 +565,7 @@ PipelineD::buildInnerQueryExecutorGeoNear(Collection* collection,
// Create a PlanExecutor whose query is the "near" predicate on 'nearFieldName' combined with
// the optional "query" argument in the $geoNear stage.
BSONObj fullQuery = geoNearStage->asNearQuery(nearFieldName);
- BSONObj proj = deps.toProjection();
+ BSONObj proj = deps.toProjectionWithoutMetadata();
BSONObj sortFromQuerySystem;
auto exec = uassertStatusOK(prepareExecutor(expCtx->opCtx,
collection,
@@ -627,7 +623,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
// The query system has the potential to use an index to provide a non-blocking sort and/or to
// use the projection to generate a covered plan. If this is possible, it is more efficient to
// let the query system handle those parts of the pipeline. If not, it is more efficient to use
- // a $sort and/or a ParsedDeps object. Thus, we will determine whether the query system can
+ // a $sort and/or a $project. Thus, we will determine whether the query system can
// provide a non-blocking sort or a covered projection before we commit to a PlanExecutor.
//
// To determine if the query system can provide a non-blocking sort, we pass the
@@ -674,6 +670,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
expCtx,
queryObj,
*projectionObj,
+ deps.metadataDeps(),
sortObj ? *sortObj : emptySort,
rewrittenGroupStage->groupId(),
aggRequest,
@@ -711,16 +708,17 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
const BSONObj metaSortProjection = BSON("$sortKey" << BSON("$meta"
<< "sortKey"));
- // The only way to get meta information (e.g. the text score) is to let the query system handle
- // the projection. In all other cases, unless the query system can do an index-covered
- // projection and avoid going to the raw record at all, it is faster to have ParsedDeps filter
- // the fields we need.
+ // TODO SERVER-42905: It should be possible to push down all eligible projections to the query
+ // layer. This code assumes that metadata is passed from the query layer to the DocumentSource
+ // layer via a projection, which is no longer true.
if (!deps.getNeedsAnyMetadata()) {
plannerOpts |= QueryPlannerParams::NO_UNCOVERED_PROJECTIONS;
}
SortPattern userSortPattern(*sortObj, expCtx);
if (sortStage && canSortBePushedDown(userSortPattern)) {
+ QueryMetadataBitSet needsSortKey;
+ needsSortKey.set(DocumentMetadataFields::MetaType::kSortKey);
// See if the query system can provide a non-blocking sort.
auto swExecutorSort =
attemptToGetExecutor(opCtx,
@@ -728,7 +726,8 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
nss,
expCtx,
queryObj,
- expCtx->needsMerge ? metaSortProjection : emptyProjection,
+ BSONObj(), // empty projection
+ expCtx->needsMerge ? needsSortKey : DepsTracker::kNoMetadata,
*sortObj,
boost::none, /* groupIdForDistinctScan */
aggRequest,
@@ -744,6 +743,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
expCtx,
queryObj,
*projectionObj,
+ deps.metadataDeps(),
*sortObj,
boost::none, /* groupIdForDistinctScan */
aggRequest,
@@ -780,13 +780,15 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
}
}
- // Either there's no sort or the query system can't provide a non-blocking sort.
+ // Either there was no $sort stage, or the query system could not provide a non-blocking
+ // sort.
*sortObj = BSONObj();
- *projectionObj = removeSortKeyMetaProjection(*projectionObj);
- const auto metadataRequired = deps.getAllRequiredMetadataTypes();
- if (metadataRequired.size() == 1 &&
- metadataRequired.front() == DepsTracker::MetadataType::SORT_KEY) {
+ // Since the DocumentSource layer will perform the sort, remove any dependencies we have on the
+ // query layer for a sort key.
+ QueryMetadataBitSet metadataDepsWithoutSortKey = deps.metadataDeps();
+ metadataDepsWithoutSortKey[DocumentMetadataFields::kSortKey] = false;
+ if (!metadataDepsWithoutSortKey.any()) {
// A sort key requirement would have prevented us from being able to add this parameter
// before, but now we know the query system won't cover the sort, so we will be able to
// compute the sort key ourselves during the $sort stage, and thus don't need a query
@@ -801,6 +803,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
expCtx,
queryObj,
*projectionObj,
+ metadataDepsWithoutSortKey,
*sortObj,
boost::none, /* groupIdForDistinctScan */
aggRequest,
@@ -814,7 +817,8 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
"Failed to determine whether query system can provide a covered projection");
}
- // The query system couldn't provide a covered or simple uncovered projection.
+ // The query system couldn't provide a covered or simple uncovered projection. Do no projections
+ // and request no metadata from the query layer.
*projectionObj = BSONObj();
// If this doesn't work, nothing will.
return attemptToGetExecutor(opCtx,
@@ -823,6 +827,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PipelineD::prep
expCtx,
queryObj,
*projectionObj,
+ DepsTracker::kNoMetadata,
*sortObj,
boost::none, /* groupIdForDistinctScan */
aggRequest,
@@ -834,8 +839,7 @@ void PipelineD::addCursorSource(Pipeline* pipeline,
boost::intrusive_ptr<DocumentSourceCursor> cursor,
DepsTracker deps,
const BSONObj& queryObj,
- const BSONObj& sortObj,
- const BSONObj& projectionObj) {
+ const BSONObj& sortObj) {
// Add the cursor to the pipeline first so that it's correctly disposed of as part of the
// pipeline if an exception is thrown during this method.
pipeline->addInitialSource(cursor);
@@ -845,19 +849,6 @@ void PipelineD::addCursorSource(Pipeline* pipeline,
if (deps.hasNoRequirements()) {
cursor->shouldProduceEmptyDocs();
}
-
- if (!projectionObj.isEmpty()) {
- cursor->setProjection(projectionObj, boost::none, deps.getNeedsAnyMetadata());
- } else {
- // There may be fewer dependencies now if the sort was covered.
- if (!sortObj.isEmpty()) {
- deps = pipeline->getDependencies(DocumentSourceMatch::isTextQuery(queryObj)
- ? DepsTracker::MetadataAvailable::kTextScore
- : DepsTracker::MetadataAvailable::kNoMetadata);
- }
-
- cursor->setProjection(deps.toProjection(), deps.toParsedDeps(), deps.getNeedsAnyMetadata());
- }
}
Timestamp PipelineD::getLatestOplogTimestamp(const Pipeline* pipeline) {
diff --git a/src/mongo/db/pipeline/pipeline_d.h b/src/mongo/db/pipeline/pipeline_d.h
index 606c91a1067..9433198c4d9 100644
--- a/src/mongo/db/pipeline/pipeline_d.h
+++ b/src/mongo/db/pipeline/pipeline_d.h
@@ -202,8 +202,7 @@ private:
boost::intrusive_ptr<DocumentSourceCursor> cursor,
DepsTracker deps,
const BSONObj& queryObj = BSONObj(),
- const BSONObj& sortObj = BSONObj(),
- const BSONObj& projectionObj = BSONObj());
+ const BSONObj& sortObj = BSONObj());
};
} // namespace mongo
diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp
index cc92f5958f2..3da457141dd 100644
--- a/src/mongo/db/pipeline/pipeline_test.cpp
+++ b/src/mongo/db/pipeline/pipeline_test.cpp
@@ -2793,13 +2793,13 @@ using PipelineDependenciesTest = AggregationContextFixture;
TEST_F(PipelineDependenciesTest, EmptyPipelineShouldRequireWholeDocument) {
auto pipeline = unittest::assertGet(Pipeline::create({}, getExpCtx()));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_TRUE(depsTracker.needWholeDocument);
- ASSERT_FALSE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_FALSE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
- depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kTextScore);
+ depsTracker = pipeline->getDependencies(DepsTracker::kOnlyTextScore);
ASSERT_TRUE(depsTracker.needWholeDocument);
- ASSERT_TRUE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_TRUE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
//
@@ -2861,7 +2861,7 @@ public:
class DocumentSourceNeedsOnlyTextScore : public DocumentSourceDependencyDummy {
public:
DepsTracker::State getDependencies(DepsTracker* deps) const final {
- deps->setNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE, true);
+ deps->setNeedsMetadata(DocumentMetadataFields::kTextScore, true);
return DepsTracker::State::EXHAUSTIVE_META;
}
@@ -2887,15 +2887,15 @@ TEST_F(PipelineDependenciesTest, ShouldRequireWholeDocumentIfAnyStageDoesNotSupp
auto notSupported = DocumentSourceDependenciesNotSupported::create();
auto pipeline = unittest::assertGet(Pipeline::create({needsASeeNext, notSupported}, ctx));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_TRUE(depsTracker.needWholeDocument);
// The inputs did not have a text score available, so we should not require a text score.
- ASSERT_FALSE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_FALSE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
// Now in the other order.
pipeline = unittest::assertGet(Pipeline::create({notSupported, needsASeeNext}, ctx));
- depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ depsTracker = pipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_TRUE(depsTracker.needWholeDocument);
}
@@ -2904,7 +2904,7 @@ TEST_F(PipelineDependenciesTest, ShouldRequireWholeDocumentIfNoStageReturnsExhau
auto needsASeeNext = DocumentSourceNeedsASeeNext::create();
auto pipeline = unittest::assertGet(Pipeline::create({needsASeeNext}, ctx));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_TRUE(depsTracker.needWholeDocument);
}
@@ -2914,7 +2914,7 @@ TEST_F(PipelineDependenciesTest, ShouldNotRequireWholeDocumentIfAnyStageReturnsE
auto needsOnlyB = DocumentSourceNeedsOnlyB::create();
auto pipeline = unittest::assertGet(Pipeline::create({needsASeeNext, needsOnlyB}, ctx));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_FALSE(depsTracker.needWholeDocument);
ASSERT_EQ(depsTracker.fields.size(), 2UL);
ASSERT_EQ(depsTracker.fields.count("a"), 1UL);
@@ -2927,9 +2927,9 @@ TEST_F(PipelineDependenciesTest, ShouldNotAddAnyRequiredFieldsAfterFirstStageWit
auto needsASeeNext = DocumentSourceNeedsASeeNext::create();
auto pipeline = unittest::assertGet(Pipeline::create({needsOnlyB, needsASeeNext}, ctx));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kNoMetadata);
ASSERT_FALSE(depsTracker.needWholeDocument);
- ASSERT_FALSE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_FALSE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
// 'needsOnlyB' claims to know all its field dependencies, so we shouldn't add any from
// 'needsASeeNext'.
@@ -2941,8 +2941,8 @@ TEST_F(PipelineDependenciesTest, ShouldNotRequireTextScoreIfThereIsNoScoreAvaila
auto ctx = getExpCtx();
auto pipeline = unittest::assertGet(Pipeline::create({}, ctx));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata);
- ASSERT_FALSE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kNoMetadata);
+ ASSERT_FALSE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(PipelineDependenciesTest, ShouldThrowIfTextScoreIsNeededButNotPresent) {
@@ -2950,21 +2950,20 @@ TEST_F(PipelineDependenciesTest, ShouldThrowIfTextScoreIsNeededButNotPresent) {
auto needsText = DocumentSourceNeedsOnlyTextScore::create();
auto pipeline = unittest::assertGet(Pipeline::create({needsText}, ctx));
- ASSERT_THROWS(pipeline->getDependencies(DepsTracker::MetadataAvailable::kNoMetadata),
- AssertionException);
+ ASSERT_THROWS(pipeline->getDependencies(DepsTracker::kNoMetadata), AssertionException);
}
TEST_F(PipelineDependenciesTest, ShouldRequireTextScoreIfAvailableAndNoStageReturnsExhaustiveMeta) {
auto ctx = getExpCtx();
auto pipeline = unittest::assertGet(Pipeline::create({}, ctx));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kTextScore);
- ASSERT_TRUE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kOnlyTextScore);
+ ASSERT_TRUE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
auto needsASeeNext = DocumentSourceNeedsASeeNext::create();
pipeline = unittest::assertGet(Pipeline::create({needsASeeNext}, ctx));
- depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kTextScore);
- ASSERT_TRUE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ depsTracker = pipeline->getDependencies(DepsTracker::kOnlyTextScore);
+ ASSERT_TRUE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
TEST_F(PipelineDependenciesTest, ShouldNotRequireTextScoreIfAvailableButDefinitelyNotNeeded) {
@@ -2973,11 +2972,11 @@ TEST_F(PipelineDependenciesTest, ShouldNotRequireTextScoreIfAvailableButDefinite
auto needsText = DocumentSourceNeedsOnlyTextScore::create();
auto pipeline = unittest::assertGet(Pipeline::create({stripsTextScore, needsText}, ctx));
- auto depsTracker = pipeline->getDependencies(DepsTracker::MetadataAvailable::kTextScore);
+ auto depsTracker = pipeline->getDependencies(DepsTracker::kOnlyTextScore);
// 'stripsTextScore' claims that no further stage will need metadata information, so we
// shouldn't have the text score as a dependency.
- ASSERT_FALSE(depsTracker.getNeedsMetadata(DepsTracker::MetadataType::TEXT_SCORE));
+ ASSERT_FALSE(depsTracker.getNeedsMetadata(DocumentMetadataFields::kTextScore));
}
} // namespace Dependencies