summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/document_value/document.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/exec/document_value/document.h')
-rw-r--r--src/mongo/db/exec/document_value/document.h93
1 files changed, 71 insertions, 22 deletions
diff --git a/src/mongo/db/exec/document_value/document.h b/src/mongo/db/exec/document_value/document.h
index 8fcfb28dd8b..062778628a0 100644
--- a/src/mongo/db/exec/document_value/document.h
+++ b/src/mongo/db/exec/document_value/document.h
@@ -100,7 +100,9 @@ public:
static constexpr StringData metaFieldSearchScore = "$searchScore"_sd;
static constexpr StringData metaFieldSearchHighlights = "$searchHighlights"_sd;
static constexpr StringData metaFieldSearchScoreDetails = "$searchScoreDetails"_sd;
+ static constexpr StringData metaFieldSearchSortValues = "$searchSortValues"_sd;
static constexpr StringData metaFieldIndexKey = "$indexKey"_sd;
+ static constexpr StringData metaFieldVectorSearchScore = "$vectorSearchScore"_sd;
static const StringDataSet allMetadataFieldNames;
@@ -191,7 +193,8 @@ public:
/**
* Get the approximate size of the Document, plus its underlying storage and sub-values. Returns
- * size in bytes.
+ * size in bytes. The return value of this function is snapshotted. All subsequent calls of this
+ * method will return the same value.
*
* Note: Some memory may be shared with other Documents or between fields within a single
* Document so this can overestimate usage.
@@ -202,6 +205,11 @@ public:
size_t getApproximateSize() const;
/**
+ * Same as 'getApproximateSize()', but this method re-computes the size on every call.
+ */
+ size_t getCurrentApproximateSize() const;
+
+ /**
* Return the approximate amount of space used by metadata.
*/
size_t getMetadataApproximateSize() const {
@@ -253,12 +261,38 @@ public:
void hash_combine(size_t& seed, const StringData::ComparatorInterface* stringComparator) const;
/**
+ * Returns true, if this document is trivially convertible to BSON, meaning the underlying
+ * storage is already in BSON format and there are no damages.
+ */
+ bool isTriviallyConvertible() const {
+ return !storage().isModified() && !storage().bsonHasMetadata();
+ }
+
+ /**
+ * Returns true, if this document is trivially convertible to BSON with metadata, meaning the
+ * underlying storage is already in BSON format and there are no damages.
+ */
+ bool isTriviallyConvertibleWithMetadata() const {
+ return !storage().isModified() && !storage().isMetadataModified();
+ }
+
+ /**
* Serializes this document to the BSONObj under construction in 'builder'. Metadata is not
* included. Throws a AssertionException if 'recursionLevel' exceeds the maximum allowable
* depth.
*/
void toBson(BSONObjBuilder* builder, size_t recursionLevel = 1) const;
- BSONObj toBson() const;
+
+ template <typename BSONTraits = BSONObj::DefaultSizeTrait>
+ BSONObj toBson() const {
+ if (isTriviallyConvertible()) {
+ return storage().bsonObj();
+ }
+
+ BSONObjBuilder bb;
+ toBson(&bb);
+ return bb.obj<BSONTraits>();
+ }
/**
* Serializes this document iff the conversion is "trivial," meaning that the underlying storage
@@ -272,7 +306,18 @@ public:
/**
* Like the 'toBson()' method, but includes metadata as top-level fields.
*/
- BSONObj toBsonWithMetaData() const;
+ void toBsonWithMetaData(BSONObjBuilder* builder) const;
+
+ template <typename BSONTraits = BSONObj::DefaultSizeTrait>
+ BSONObj toBsonWithMetaData() const {
+ if (isTriviallyConvertibleWithMetadata()) {
+ return storage().bsonObj();
+ }
+
+ BSONObjBuilder bb;
+ toBsonWithMetaData(&bb);
+ return bb.obj<BSONTraits>();
+ }
/**
* Like Document(BSONObj) but treats top-level fields with special names as metadata.
@@ -370,12 +415,6 @@ private:
getNestedFieldNonCachingHelper(const FieldPath& dottedField, size_t level) const;
boost::intrusive_ptr<const DocumentStorage> _storage;
-
- /**
- * Returns the approximate size of this `Document` instance without considering the size of its
- * backing BSON object.
- */
- size_t getApproximateSizeWithoutBackingBSON() const;
};
//
@@ -511,13 +550,11 @@ public:
}
/**
- * Replace the current base Document with bson.
- *
- * The paramater 'stripMetadata' controls whether we strip the metadata fields from the
- * underlying bson when converting the document object back to bson.
+ * Replace the current base Document with the BSON object. Setting 'bsonHasMetadata' to true
+ * signals that the BSON object contains metadata fields.
*/
- void reset(const BSONObj& bson, bool stripMetadata) {
- storage().reset(bson, stripMetadata);
+ void reset(const BSONObj& bson, bool bsonHasMetadata) {
+ storage().reset(bson, bsonHasMetadata);
}
/** Add the given field to the Document.
@@ -654,6 +691,7 @@ public:
* TODO: there are some optimizations that may make sense at freeze time.
*/
Document freeze() {
+ resetSnapshottedApproximateSize();
// This essentially moves _storage into a new Document by way of temp.
Document ret;
boost::intrusive_ptr<const DocumentStorage> temp(storagePtr(), /*inc_ref_count=*/false);
@@ -672,8 +710,12 @@ public:
* Note that unlike freeze(), this indicates intention to continue
* modifying this document. The returned Document will not observe
* future changes to this MutableDocument.
+ *
+ * Note that the computed snapshotted approximate size of the Document
+ * is not preserved across calls.
*/
Document peek() {
+ resetSnapshottedApproximateSize();
return Document(storagePtr());
}
@@ -695,13 +737,13 @@ public:
storage().makeOwned();
}
- /** Create a new document storage with the BSON object.
- *
- * The optional paramater 'stripMetadata' controls whether we strip the metadata fields (the
- * complete list is in Document::allMetadataFieldNames).
+ /**
+ * Creates a new document storage with the BSON object. Setting 'bsonHasMetadata' to true
+ * signals that the BSON object contains metadata fields (the complete list is in
+ * Document::allMetadataFieldNames).
*/
- DocumentStorage& newStorageWithBson(const BSONObj& bson, bool stripMetadata) {
- reset(make_intrusive<DocumentStorage>(bson, stripMetadata, false, 0));
+ DocumentStorage& newStorageWithBson(const BSONObj& bson, bool bsonHasMetadata) {
+ reset(make_intrusive<DocumentStorage>(bson, bsonHasMetadata, false, 0));
return const_cast<DocumentStorage&>(*storagePtr());
}
@@ -739,12 +781,19 @@ private:
MutableValue getNestedFieldHelper(const FieldPath& dottedField, size_t level);
MutableValue getNestedFieldHelper(const std::vector<Position>& positions, size_t level);
- // this should only be called by storage methods and peek/freeze
+ // this should only be called by storage methods and peek/freeze/resetsnapshottedApproximateSize
const DocumentStorage* storagePtr() const {
dassert(!_storage || typeid(*_storage) == typeid(const DocumentStorage));
return static_cast<const DocumentStorage*>(_storage);
}
+ void resetSnapshottedApproximateSize() {
+ auto mutableStorage = const_cast<DocumentStorage*>(storagePtr());
+ if (mutableStorage) {
+ mutableStorage->resetSnapshottedApproximateSize();
+ }
+ }
+
// These are both const to prevent modifications bypassing storage() method.
// They always point to NULL or an object with dynamic type DocumentStorage.
const RefCountable* _storageHolder; // Only used in constructors and destructor