summaryrefslogtreecommitdiff
path: root/src/mongo/db/index/sort_key_generator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/index/sort_key_generator.cpp')
-rw-r--r--src/mongo/db/index/sort_key_generator.cpp99
1 files changed, 41 insertions, 58 deletions
diff --git a/src/mongo/db/index/sort_key_generator.cpp b/src/mongo/db/index/sort_key_generator.cpp
index 97abfe097a7..a09622bb316 100644
--- a/src/mongo/db/index/sort_key_generator.cpp
+++ b/src/mongo/db/index/sort_key_generator.cpp
@@ -76,30 +76,15 @@ SortKeyGenerator::SortKeyGenerator(SortPattern sortPattern, const CollatorInterf
Ordering::make(_sortSpecWithoutMeta));
}
-// TODO (SERVER-42836): Once WorkingSetMember objects store a Document (SERVER-42181), this function
-// will be able to use the Document overload of computeSortKeyFromDocument, and it will be able to
-// store the text score with the Document instead of in a separate SortKeyGenerator::Metadata
-// object.
-StatusWith<Value> SortKeyGenerator::computeSortKey(const WorkingSetMember& wsm) const {
+Value SortKeyGenerator::computeSortKey(const WorkingSetMember& wsm) const {
if (wsm.hasObj()) {
- SortKeyGenerator::Metadata metadata;
- if (_sortHasMeta && wsm.metadata().hasTextScore()) {
- metadata.textScore = wsm.metadata().getTextScore();
- }
- auto statusWithSortKeyObj = computeSortKeyFromDocument(wsm.doc.value().toBson(), &metadata);
- if (!statusWithSortKeyObj.isOK()) {
- return statusWithSortKeyObj.getStatus();
- }
-
- return DocumentMetadataFields::deserializeSortKey(isSingleElementKey(),
- statusWithSortKeyObj.getValue());
+ return computeSortKeyFromDocument(wsm.doc.value(), wsm.metadata());
}
return computeSortKeyFromIndexKey(wsm);
}
-StatusWith<Value> SortKeyGenerator::computeSortKeyFromIndexKey(
- const WorkingSetMember& member) const {
+Value SortKeyGenerator::computeSortKeyFromIndexKey(const WorkingSetMember& member) const {
invariant(member.getState() == WorkingSetMember::RID_AND_IDX);
invariant(!_sortHasMeta);
@@ -118,16 +103,9 @@ StatusWith<Value> SortKeyGenerator::computeSortKeyFromIndexKey(
return DocumentMetadataFields::deserializeSortKey(isSingleElementKey(), objBuilder.obj());
}
-StatusWith<BSONObj> SortKeyGenerator::computeSortKeyFromDocument(const BSONObj& obj,
- const Metadata* metadata) const {
- if (_sortHasMeta) {
- invariant(metadata);
- }
-
- auto sortKeyNoMetadata = computeSortKeyFromDocumentWithoutMetadata(obj);
- if (!sortKeyNoMetadata.isOK()) {
- return sortKeyNoMetadata;
- }
+BSONObj SortKeyGenerator::computeSortKeyFromDocument(const BSONObj& obj,
+ const DocumentMetadataFields& metadata) const {
+ auto sortKeyNoMetadata = uassertStatusOK(computeSortKeyFromDocumentWithoutMetadata(obj));
if (!_sortHasMeta) {
// We don't have to worry about $meta sort, so the index key becomes the sort key.
@@ -137,24 +115,27 @@ StatusWith<BSONObj> SortKeyGenerator::computeSortKeyFromDocument(const BSONObj&
BSONObjBuilder mergedKeyBob;
// Merge metadata into the key.
- BSONObjIterator sortKeyIt(sortKeyNoMetadata.getValue());
+ BSONObjIterator sortKeyIt(sortKeyNoMetadata);
for (auto& part : _sortPattern) {
if (part.fieldPath) {
invariant(sortKeyIt.more());
mergedKeyBob.append(sortKeyIt.next());
continue;
}
+
+ // Create a Document that represents the input object and its metadata together, so we can
+ // use it to evaluate the ExpressionMeta for this part of the sort pattern. This operation
+ // copies the data in 'metadata' but not any of the data in the 'obj' BSON.
+ MutableDocument documentWithMetdata(Document{obj});
+ documentWithMetdata.setMetadata(DocumentMetadataFields(metadata));
+
invariant(part.expression);
- switch (part.expression->getMetaType()) {
- case DocumentMetadataFields::MetaType::kTextScore: {
- mergedKeyBob.append("", metadata->textScore);
- continue;
- }
- case DocumentMetadataFields::MetaType::kRandVal: {
- mergedKeyBob.append("", metadata->randVal);
- continue;
- }
- default: { MONGO_UNREACHABLE; }
+ auto value =
+ part.expression->evaluate(documentWithMetdata.freeze(), nullptr /* variables */);
+ if (!value.missing()) {
+ value.addToBsonObj(&mergedKeyBob, ""_sd);
+ } else {
+ mergedKeyBob.appendNull("");
}
}
@@ -231,7 +212,9 @@ Value SortKeyGenerator::getCollationComparisonKey(const Value& val) const {
}
StatusWith<Value> SortKeyGenerator::extractKeyPart(
- const Document& doc, const SortPattern::SortPatternPart& patternPart) const {
+ const Document& doc,
+ const DocumentMetadataFields& metadata,
+ const SortPattern::SortPatternPart& patternPart) const {
Value plainKey;
if (patternPart.fieldPath) {
invariant(!patternPart.expression);
@@ -243,22 +226,28 @@ StatusWith<Value> SortKeyGenerator::extractKeyPart(
plainKey = key.getValue();
} else {
invariant(patternPart.expression);
+ // ExpressionMeta expects metadata to be attached to the document.
+ MutableDocument documentWithMetadata(doc);
+ documentWithMetadata.setMetadata(DocumentMetadataFields(metadata));
+
// ExpressionMeta does not use Variables.
- plainKey = patternPart.expression->evaluate(doc, nullptr /* variables */);
+ plainKey = patternPart.expression->evaluate(documentWithMetadata.freeze(),
+ nullptr /* variables */);
}
- return getCollationComparisonKey(plainKey);
+ return plainKey.missing() ? Value{BSONNULL} : getCollationComparisonKey(plainKey);
}
-StatusWith<Value> SortKeyGenerator::extractKeyFast(const Document& doc) const {
+StatusWith<Value> SortKeyGenerator::extractKeyFast(const Document& doc,
+ const DocumentMetadataFields& metadata) const {
if (_sortPattern.isSingleElementKey()) {
- return extractKeyPart(doc, _sortPattern[0]);
+ return extractKeyPart(doc, metadata, _sortPattern[0]);
}
std::vector<Value> keys;
keys.reserve(_sortPattern.size());
for (auto&& keyPart : _sortPattern) {
- auto extractedKey = extractKeyPart(doc, keyPart);
+ auto extractedKey = extractKeyPart(doc, metadata, keyPart);
if (!extractedKey.isOK()) {
// We can't use the fast path, so bail out.
return extractedKey;
@@ -269,24 +258,18 @@ StatusWith<Value> SortKeyGenerator::extractKeyFast(const Document& doc) const {
return Value{std::move(keys)};
}
-BSONObj SortKeyGenerator::extractKeyWithArray(const Document& doc) const {
- SortKeyGenerator::Metadata metadata;
- if (doc.metadata().hasTextScore()) {
- metadata.textScore = doc.metadata().getTextScore();
- }
- if (doc.metadata().hasRandVal()) {
- metadata.randVal = doc.metadata().getRandVal();
- }
-
+BSONObj SortKeyGenerator::extractKeyWithArray(const Document& doc,
+ const DocumentMetadataFields& metadata) const {
// Convert the Document to a BSONObj, but only do the conversion for the paths we actually need.
// Then run the result through the SortKeyGenerator to obtain the final sort key.
auto bsonDoc = _sortPattern.documentToBsonWithSortPaths(doc);
- return uassertStatusOK(computeSortKeyFromDocument(bsonDoc, &metadata));
+ return computeSortKeyFromDocument(bsonDoc, metadata);
}
-Value SortKeyGenerator::computeSortKeyFromDocument(const Document& doc) const {
+Value SortKeyGenerator::computeSortKeyFromDocument(const Document& doc,
+ const DocumentMetadataFields& metadata) const {
// This fast pass directly generates a Value.
- auto fastKey = extractKeyFast(doc);
+ auto fastKey = extractKeyFast(doc, metadata);
if (fastKey.isOK()) {
return std::move(fastKey.getValue());
}
@@ -295,7 +278,7 @@ Value SortKeyGenerator::computeSortKeyFromDocument(const Document& doc) const {
// form like BSONObj {'': 1, '': [2, 3]}) and converts it to a Value (Value [1, [2, 3]] in the
// earlier example).
return DocumentMetadataFields::deserializeSortKey(_sortPattern.isSingleElementKey(),
- extractKeyWithArray(doc));
+ extractKeyWithArray(doc, metadata));
}
} // namespace mongo