@@ -76,15 +76,30 @@ SortKeyGenerator::SortKeyGenerator(SortPattern sortPattern, const CollatorInterf
76
76
Ordering::make (_sortSpecWithoutMeta));
77
77
}
78
78
79
- Value SortKeyGenerator::computeSortKey (const WorkingSetMember& wsm) const {
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 {
80
84
if (wsm.hasObj ()) {
81
- return computeSortKeyFromDocument (wsm.doc .value (), wsm.metadata ());
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 ());
82
96
}
83
97
84
98
return computeSortKeyFromIndexKey (wsm);
85
99
}
86
100
87
- Value SortKeyGenerator::computeSortKeyFromIndexKey (const WorkingSetMember& member) const {
101
+ StatusWith<Value> SortKeyGenerator::computeSortKeyFromIndexKey (
102
+ const WorkingSetMember& member) const {
88
103
invariant (member.getState () == WorkingSetMember::RID_AND_IDX);
89
104
invariant (!_sortHasMeta);
90
105
@@ -103,9 +118,16 @@ Value SortKeyGenerator::computeSortKeyFromIndexKey(const WorkingSetMember& membe
103
118
return DocumentMetadataFields::deserializeSortKey (isSingleElementKey (), objBuilder.obj ());
104
119
}
105
120
106
- BSONObj SortKeyGenerator::computeSortKeyFromDocument (const BSONObj& obj,
107
- const DocumentMetadataFields& metadata) const {
108
- auto sortKeyNoMetadata = uassertStatusOK (computeSortKeyFromDocumentWithoutMetadata (obj));
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
+ }
109
131
110
132
if (!_sortHasMeta) {
111
133
// We don't have to worry about $meta sort, so the index key becomes the sort key.
@@ -115,27 +137,24 @@ BSONObj SortKeyGenerator::computeSortKeyFromDocument(const BSONObj& obj,
115
137
BSONObjBuilder mergedKeyBob;
116
138
117
139
// Merge metadata into the key.
118
- BSONObjIterator sortKeyIt (sortKeyNoMetadata);
140
+ BSONObjIterator sortKeyIt (sortKeyNoMetadata. getValue () );
119
141
for (auto & part : _sortPattern) {
120
142
if (part.fieldPath ) {
121
143
invariant (sortKeyIt.more ());
122
144
mergedKeyBob.append (sortKeyIt.next ());
123
145
continue ;
124
146
}
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
-
132
147
invariant (part.expression );
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 (" " );
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; }
139
158
}
140
159
}
141
160
@@ -212,9 +231,7 @@ Value SortKeyGenerator::getCollationComparisonKey(const Value& val) const {
212
231
}
213
232
214
233
StatusWith<Value> SortKeyGenerator::extractKeyPart (
215
- const Document& doc,
216
- const DocumentMetadataFields& metadata,
217
- const SortPattern::SortPatternPart& patternPart) const {
234
+ const Document& doc, const SortPattern::SortPatternPart& patternPart) const {
218
235
Value plainKey;
219
236
if (patternPart.fieldPath ) {
220
237
invariant (!patternPart.expression );
@@ -226,28 +243,22 @@ StatusWith<Value> SortKeyGenerator::extractKeyPart(
226
243
plainKey = key.getValue ();
227
244
} else {
228
245
invariant (patternPart.expression );
229
- // ExpressionMeta expects metadata to be attached to the document.
230
- MutableDocument documentWithMetadata (doc);
231
- documentWithMetadata.setMetadata (DocumentMetadataFields (metadata));
232
-
233
246
// ExpressionMeta does not use Variables.
234
- plainKey = patternPart.expression ->evaluate (documentWithMetadata.freeze (),
235
- nullptr /* variables */ );
247
+ plainKey = patternPart.expression ->evaluate (doc, nullptr /* variables */ );
236
248
}
237
249
238
- return plainKey. missing () ? Value{BSONNULL} : getCollationComparisonKey (plainKey);
250
+ return getCollationComparisonKey (plainKey);
239
251
}
240
252
241
- StatusWith<Value> SortKeyGenerator::extractKeyFast (const Document& doc,
242
- const DocumentMetadataFields& metadata) const {
253
+ StatusWith<Value> SortKeyGenerator::extractKeyFast (const Document& doc) const {
243
254
if (_sortPattern.isSingleElementKey ()) {
244
- return extractKeyPart (doc, metadata, _sortPattern[0 ]);
255
+ return extractKeyPart (doc, _sortPattern[0 ]);
245
256
}
246
257
247
258
std::vector<Value> keys;
248
259
keys.reserve (_sortPattern.size ());
249
260
for (auto && keyPart : _sortPattern) {
250
- auto extractedKey = extractKeyPart (doc, metadata, keyPart);
261
+ auto extractedKey = extractKeyPart (doc, keyPart);
251
262
if (!extractedKey.isOK ()) {
252
263
// We can't use the fast path, so bail out.
253
264
return extractedKey;
@@ -258,18 +269,24 @@ StatusWith<Value> SortKeyGenerator::extractKeyFast(const Document& doc,
258
269
return Value{std::move (keys)};
259
270
}
260
271
261
- BSONObj SortKeyGenerator::extractKeyWithArray (const Document& doc,
262
- const DocumentMetadataFields& metadata) const {
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
+
263
281
// Convert the Document to a BSONObj, but only do the conversion for the paths we actually need.
264
282
// Then run the result through the SortKeyGenerator to obtain the final sort key.
265
283
auto bsonDoc = _sortPattern.documentToBsonWithSortPaths (doc);
266
- return computeSortKeyFromDocument (bsonDoc, metadata);
284
+ return uassertStatusOK ( computeSortKeyFromDocument (bsonDoc, & metadata) );
267
285
}
268
286
269
- Value SortKeyGenerator::computeSortKeyFromDocument (const Document& doc,
270
- const DocumentMetadataFields& metadata) const {
287
+ Value SortKeyGenerator::computeSortKeyFromDocument (const Document& doc) const {
271
288
// This fast pass directly generates a Value.
272
- auto fastKey = extractKeyFast (doc, metadata );
289
+ auto fastKey = extractKeyFast (doc);
273
290
if (fastKey.isOK ()) {
274
291
return std::move (fastKey.getValue ());
275
292
}
@@ -278,7 +295,7 @@ Value SortKeyGenerator::computeSortKeyFromDocument(const Document& doc,
278
295
// form like BSONObj {'': 1, '': [2, 3]}) and converts it to a Value (Value [1, [2, 3]] in the
279
296
// earlier example).
280
297
return DocumentMetadataFields::deserializeSortKey (_sortPattern.isSingleElementKey (),
281
- extractKeyWithArray (doc, metadata ));
298
+ extractKeyWithArray (doc));
282
299
}
283
300
284
301
} // namespace mongo
0 commit comments