Skip to content

Commit 42ad6f9

Browse files
committed
SERVER-42177 Implement cheap metadata transfer between Document and WorkingSetMember.
1 parent ab48766 commit 42ad6f9

File tree

4 files changed

+84
-8
lines changed

4 files changed

+84
-8
lines changed

src/mongo/db/exec/working_set.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,23 @@ class WorkingSetMember {
285285
return _metadata;
286286
}
287287

288+
/**
289+
* Clears all metadata fields inside this WorkingSetMember, and returns a structure containing
290+
* that extracted metadata to the caller. The metadata can then be attached to a new
291+
* WorkingSetMember or to another data structure that houses metadata.
292+
*/
293+
DocumentMetadataFields releaseMetadata() {
294+
return std::move(_metadata);
295+
}
296+
297+
/**
298+
* Transfers metadata fields to this working set member. By pairs of calls to releaseMetadata()
299+
* and setMetadata(), callers can cheaply transfer metadata between WorkingSetMembers.
300+
*/
301+
void setMetadata(DocumentMetadataFields&& metadata) {
302+
_metadata = std::move(metadata);
303+
}
304+
288305
private:
289306
friend class WorkingSet;
290307

src/mongo/db/exec/working_set_test.cpp

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,17 @@
2727
* it in the license file.
2828
*/
2929

30-
/**
31-
* This file contains tests for mongo/db/exec/working_set.cpp
32-
*/
33-
30+
#include "mongo/platform/basic.h"
3431

3532
#include "mongo/db/exec/working_set.h"
3633
#include "mongo/db/jsobj.h"
3734
#include "mongo/db/json.h"
35+
#include "mongo/db/pipeline/document.h"
3836
#include "mongo/db/storage/snapshot.h"
3937
#include "mongo/unittest/unittest.h"
4038
#include "mongo/util/assert_util.h"
4139

42-
using namespace mongo;
43-
44-
namespace {
40+
namespace mongo {
4541

4642
using std::string;
4743

@@ -156,4 +152,42 @@ TEST_F(WorkingSetFixture, getDottedFieldFromIndex) {
156152
ASSERT_FALSE(member->getFieldDotted("y", &elt));
157153
}
158154

159-
} // namespace
155+
TEST_F(WorkingSetFixture, MetadataCanBeCorrectlyTransferredBackAndForthFromDocument) {
156+
// Add some metadata to the WSM.
157+
member->metadata().setTextScore(1.2);
158+
member->metadata().setSearchScore(3.4);
159+
160+
// Test that the metadata can be extracted from the WSM.
161+
auto releasedMetadata = member->releaseMetadata();
162+
ASSERT_FALSE(member->metadata());
163+
ASSERT_FALSE(member->metadata().hasTextScore());
164+
ASSERT_FALSE(member->metadata().hasSearchScore());
165+
ASSERT_TRUE(releasedMetadata);
166+
ASSERT_TRUE(releasedMetadata.hasTextScore());
167+
ASSERT_TRUE(releasedMetadata.hasSearchScore());
168+
169+
// Test that the extracted metadata can be added to a Document.
170+
Document document;
171+
MutableDocument md{std::move(document)};
172+
md.setMetadata(std::move(releasedMetadata));
173+
document = md.freeze();
174+
ASSERT_FALSE(releasedMetadata);
175+
ASSERT_FALSE(releasedMetadata.hasTextScore());
176+
ASSERT_FALSE(releasedMetadata.hasSearchScore());
177+
ASSERT_TRUE(document.metadata());
178+
ASSERT_TRUE(document.metadata().hasTextScore());
179+
ASSERT_TRUE(document.metadata().hasSearchScore());
180+
181+
// Test that metadata can be transferred back to the WSM.
182+
MutableDocument md2{std::move(document)};
183+
member->setMetadata(md2.releaseMetadata());
184+
document = md2.freeze();
185+
ASSERT_FALSE(document.metadata());
186+
ASSERT_FALSE(document.metadata().hasTextScore());
187+
ASSERT_FALSE(document.metadata().hasSearchScore());
188+
ASSERT_TRUE(member->metadata());
189+
ASSERT_TRUE(member->metadata().hasTextScore());
190+
ASSERT_TRUE(member->metadata().hasSearchScore());
191+
}
192+
193+
} // namespace mongo

src/mongo/db/pipeline/document.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,23 @@ class MutableDocument {
524524
return storage().metadata();
525525
}
526526

527+
/**
528+
* Clears all metadata fields inside this Document, and returns a structure containing that
529+
* extracted metadata to the caller. The metadata can then be attached to a new Document or to
530+
* another data structure that houses metadata.
531+
*/
532+
DocumentMetadataFields releaseMetadata() {
533+
return storage().releaseMetadata();
534+
}
535+
536+
/**
537+
* Transfers metadata fields to this Document. By pairs of calls to releaseMetadata() and
538+
* setMetadata(), callers can cheaply transfer metadata between Documents.
539+
*/
540+
void setMetadata(DocumentMetadataFields&& metadata) {
541+
storage().setMetadata(std::move(metadata));
542+
}
543+
527544
/** Convert to a read-only document and release reference.
528545
*
529546
* Call this to indicate that you are done with this Document and will

src/mongo/db/pipeline/document_internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,14 @@ class DocumentStorage : public RefCountable {
407407
return _metadataFields;
408408
}
409409

410+
DocumentMetadataFields releaseMetadata() {
411+
return std::move(_metadataFields);
412+
}
413+
414+
void setMetadata(DocumentMetadataFields&& metadata) {
415+
_metadataFields = std::move(metadata);
416+
}
417+
410418
static unsigned hashKey(StringData name) {
411419
// TODO consider FNV-1a once we have a better benchmark corpus
412420
unsigned out;

0 commit comments

Comments
 (0)