@@ -76,30 +76,15 @@ SortKeyGenerator::SortKeyGenerator(SortPattern sortPattern, const CollatorInterf
7676 Ordering::make (_sortSpecWithoutMeta));
7777}
7878
79- // TODO (SERVER-42836): Once WorkingSetMember objects store a Document (SERVER-42181), this function
80- // will be able to use the Document overload of computeSortKeyFromDocument, and it will be able to
81- // store the text score with the Document instead of in a separate SortKeyGenerator::Metadata
82- // object.
83- StatusWith<Value> SortKeyGenerator::computeSortKey (const WorkingSetMember& wsm) const {
79+ Value SortKeyGenerator::computeSortKey (const WorkingSetMember& wsm) const {
8480 if (wsm.hasObj ()) {
85- SortKeyGenerator::Metadata metadata;
86- if (_sortHasMeta && wsm.metadata ().hasTextScore ()) {
87- metadata.textScore = wsm.metadata ().getTextScore ();
88- }
89- auto statusWithSortKeyObj = computeSortKeyFromDocument (wsm.doc .value ().toBson (), &metadata);
90- if (!statusWithSortKeyObj.isOK ()) {
91- return statusWithSortKeyObj.getStatus ();
92- }
93-
94- return DocumentMetadataFields::deserializeSortKey (isSingleElementKey (),
95- statusWithSortKeyObj.getValue ());
81+ return computeSortKeyFromDocument (wsm.doc .value (), wsm.metadata ());
9682 }
9783
9884 return computeSortKeyFromIndexKey (wsm);
9985}
10086
101- StatusWith<Value> SortKeyGenerator::computeSortKeyFromIndexKey (
102- const WorkingSetMember& member) const {
87+ Value SortKeyGenerator::computeSortKeyFromIndexKey (const WorkingSetMember& member) const {
10388 invariant (member.getState () == WorkingSetMember::RID_AND_IDX);
10489 invariant (!_sortHasMeta);
10590
@@ -118,16 +103,9 @@ StatusWith<Value> SortKeyGenerator::computeSortKeyFromIndexKey(
118103 return DocumentMetadataFields::deserializeSortKey (isSingleElementKey (), objBuilder.obj ());
119104}
120105
121- StatusWith<BSONObj> SortKeyGenerator::computeSortKeyFromDocument (const BSONObj& obj,
122- const Metadata* metadata) const {
123- if (_sortHasMeta) {
124- invariant (metadata);
125- }
126-
127- auto sortKeyNoMetadata = computeSortKeyFromDocumentWithoutMetadata (obj);
128- if (!sortKeyNoMetadata.isOK ()) {
129- return sortKeyNoMetadata;
130- }
106+ BSONObj SortKeyGenerator::computeSortKeyFromDocument (const BSONObj& obj,
107+ const DocumentMetadataFields& metadata) const {
108+ auto sortKeyNoMetadata = uassertStatusOK (computeSortKeyFromDocumentWithoutMetadata (obj));
131109
132110 if (!_sortHasMeta) {
133111 // 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&
137115 BSONObjBuilder mergedKeyBob;
138116
139117 // Merge metadata into the key.
140- BSONObjIterator sortKeyIt (sortKeyNoMetadata. getValue () );
118+ BSONObjIterator sortKeyIt (sortKeyNoMetadata);
141119 for (auto & part : _sortPattern) {
142120 if (part.fieldPath ) {
143121 invariant (sortKeyIt.more ());
144122 mergedKeyBob.append (sortKeyIt.next ());
145123 continue ;
146124 }
125+
126+ // Create a Document that represents the input object and its metadata together, so we can
127+ // use it to evaluate the ExpressionMeta for this part of the sort pattern. This operation
128+ // copies the data in 'metadata' but not any of the data in the 'obj' BSON.
129+ MutableDocument documentWithMetdata (Document{obj});
130+ documentWithMetdata.setMetadata (DocumentMetadataFields (metadata));
131+
147132 invariant (part.expression );
148- switch (part.expression ->getMetaType ()) {
149- case DocumentMetadataFields::MetaType::kTextScore : {
150- mergedKeyBob.append (" " , metadata->textScore );
151- continue ;
152- }
153- case DocumentMetadataFields::MetaType::kRandVal : {
154- mergedKeyBob.append (" " , metadata->randVal );
155- continue ;
156- }
157- default : { MONGO_UNREACHABLE; }
133+ auto value =
134+ part.expression ->evaluate (documentWithMetdata.freeze (), nullptr /* variables */ );
135+ if (!value.missing ()) {
136+ value.addToBsonObj (&mergedKeyBob, " " _sd);
137+ } else {
138+ mergedKeyBob.appendNull (" " );
158139 }
159140 }
160141
@@ -231,7 +212,9 @@ Value SortKeyGenerator::getCollationComparisonKey(const Value& val) const {
231212}
232213
233214StatusWith<Value> SortKeyGenerator::extractKeyPart (
234- const Document& doc, const SortPattern::SortPatternPart& patternPart) const {
215+ const Document& doc,
216+ const DocumentMetadataFields& metadata,
217+ const SortPattern::SortPatternPart& patternPart) const {
235218 Value plainKey;
236219 if (patternPart.fieldPath ) {
237220 invariant (!patternPart.expression );
@@ -243,22 +226,28 @@ StatusWith<Value> SortKeyGenerator::extractKeyPart(
243226 plainKey = key.getValue ();
244227 } else {
245228 invariant (patternPart.expression );
229+ // ExpressionMeta expects metadata to be attached to the document.
230+ MutableDocument documentWithMetadata (doc);
231+ documentWithMetadata.setMetadata (DocumentMetadataFields (metadata));
232+
246233 // ExpressionMeta does not use Variables.
247- plainKey = patternPart.expression ->evaluate (doc, nullptr /* variables */ );
234+ plainKey = patternPart.expression ->evaluate (documentWithMetadata.freeze (),
235+ nullptr /* variables */ );
248236 }
249237
250- return getCollationComparisonKey (plainKey);
238+ return plainKey. missing () ? Value{BSONNULL} : getCollationComparisonKey (plainKey);
251239}
252240
253- StatusWith<Value> SortKeyGenerator::extractKeyFast (const Document& doc) const {
241+ StatusWith<Value> SortKeyGenerator::extractKeyFast (const Document& doc,
242+ const DocumentMetadataFields& metadata) const {
254243 if (_sortPattern.isSingleElementKey ()) {
255- return extractKeyPart (doc, _sortPattern[0 ]);
244+ return extractKeyPart (doc, metadata, _sortPattern[0 ]);
256245 }
257246
258247 std::vector<Value> keys;
259248 keys.reserve (_sortPattern.size ());
260249 for (auto && keyPart : _sortPattern) {
261- auto extractedKey = extractKeyPart (doc, keyPart);
250+ auto extractedKey = extractKeyPart (doc, metadata, keyPart);
262251 if (!extractedKey.isOK ()) {
263252 // We can't use the fast path, so bail out.
264253 return extractedKey;
@@ -269,24 +258,18 @@ StatusWith<Value> SortKeyGenerator::extractKeyFast(const Document& doc) const {
269258 return Value{std::move (keys)};
270259}
271260
272- BSONObj SortKeyGenerator::extractKeyWithArray (const Document& doc) const {
273- SortKeyGenerator::Metadata metadata;
274- if (doc.metadata ().hasTextScore ()) {
275- metadata.textScore = doc.metadata ().getTextScore ();
276- }
277- if (doc.metadata ().hasRandVal ()) {
278- metadata.randVal = doc.metadata ().getRandVal ();
279- }
280-
261+ BSONObj SortKeyGenerator::extractKeyWithArray (const Document& doc,
262+ const DocumentMetadataFields& metadata) const {
281263 // Convert the Document to a BSONObj, but only do the conversion for the paths we actually need.
282264 // Then run the result through the SortKeyGenerator to obtain the final sort key.
283265 auto bsonDoc = _sortPattern.documentToBsonWithSortPaths (doc);
284- return uassertStatusOK ( computeSortKeyFromDocument (bsonDoc, & metadata) );
266+ return computeSortKeyFromDocument (bsonDoc, metadata);
285267}
286268
287- Value SortKeyGenerator::computeSortKeyFromDocument (const Document& doc) const {
269+ Value SortKeyGenerator::computeSortKeyFromDocument (const Document& doc,
270+ const DocumentMetadataFields& metadata) const {
288271 // This fast pass directly generates a Value.
289- auto fastKey = extractKeyFast (doc);
272+ auto fastKey = extractKeyFast (doc, metadata );
290273 if (fastKey.isOK ()) {
291274 return std::move (fastKey.getValue ());
292275 }
@@ -295,7 +278,7 @@ Value SortKeyGenerator::computeSortKeyFromDocument(const Document& doc) const {
295278 // form like BSONObj {'': 1, '': [2, 3]}) and converts it to a Value (Value [1, [2, 3]] in the
296279 // earlier example).
297280 return DocumentMetadataFields::deserializeSortKey (_sortPattern.isSingleElementKey (),
298- extractKeyWithArray (doc));
281+ extractKeyWithArray (doc, metadata ));
299282}
300283
301284} // namespace mongo
0 commit comments