How to get the size of single document in Mongodb?

JavascriptMongodbDocumentObjectidObjectsize

Javascript Problem Overview


I encountered a strange behavior of mongo and I would like to clarify it a bit...
My request is simple as that: I would like to get a size of single document in collection. I found two possible solutions:

  • Object.bsonsize - some javascript method that should return a size in bytes
  • db.collection.stats() - where there is a line 'avgObjSize' that produce some "aggregated"(average) size view on the data. It simply represents average size of single document.

  • When I create test collection with only one document, both functions returns different values. How is it possible?
    Does it exist some other method to get a size of a mongo document?

Here, I provide some code I perform testing on:

  1. I created new database 'test' and input simple document with only one attribute: type:"auto"

     db.test.insert({type:"auto"})
    
  2. output from stats() function call: db.test.stats():

     { 
       "ns" : "test.test",
       "count" : 1,
       "size" : 40,
       "avgObjSize" : 40,
       "storageSize" : 4096,
       "numExtents" : 1,
       "nindexes" : 1,
       "lastExtentSize" : 4096,
       "paddingFactor" : 1,
       "systemFlags" : 1,
       "userFlags" : 0,
       "totalIndexSize" : 8176,
       "indexSizes" : {
             "_id_" : 8176
     },
     "ok" : 1
    }
    
  3. output from bsonsize function call: Object.bsonsize(db.test.find({test:"auto"}))

     481
    

Javascript Solutions


Solution 1 - Javascript

In the previous call of Object.bsonsize(), Mongodb returned the size of the cursor, rather than the document.

Correct way is to use this command:

Object.bsonsize(db.test.findOne())

With findOne(), you can define your query for a specific document:

Object.bsonsize(db.test.findOne({type:"auto"}))

This will return the correct size (in bytes) of the particular document.

Solution 2 - Javascript

MAXIMUM DOCUMENT SIZE 16 MiB (source)


If you have version >=4.4 ($bsonSize source)

db.users.aggregate([
  {
    "$project": {
      "size_bytes": { "$bsonSize": "$$ROOT" },
      "size_KB": { "$divide": [{"$bsonSize": "$$ROOT"}, 1000] },
      "size_MB": { "$divide": [{"$bsonSize": "$$ROOT"}, 1000000] }
    }
  }
])

If you have version <4.4 (Object.bsonSize() source)

You can use this script for get a real size:

db.users.find().forEach(function(obj)
{
  var size = Object.bsonsize(obj);
  print('_id: '+obj._id+' || Size: '+size+'B -> '+Math.round(size/(1000))+'KB -> '+Math.round(size/(1000*1000))+'MB (max 16MB)');
});

Note: If your IDs are 64-bit integers, the above will truncate the ID value on printing! If that's the case, you can use instead:

db.users.find().forEach(function(obj)
{
  var size = Object.bsonsize(obj);
  var stats =
  {
    '_id': obj._id, 
    'bytes': size, 
    'KB': Math.round(size/(1000)), 
    'MB': Math.round(size/(1000*1000))
  };
  print(stats);
});

This also has the advantage of returning JSON, so a GUI like RoboMongo can tabulate it!


edit : thanks to @zAlbee for your suggest completion.

Solution 3 - Javascript

The effective amount of space the document will take in the collection will be more than the size of your document because of the Record Padding mechanism.

This is why there is a difference between the outputs of the db.test.stats() and Object.bsonsize(..).

To get the exact size (in bytes) of the document, stick to the Object.bsonsize() function.

Solution 4 - Javascript

With mongodb 4.4 (upcoming), You can use bsonSize operator to get the document size.

db.test.aggregate([
  {
    "$project": {
      "name": 1,
      "object_size": { "$bsonSize": "$$ROOT" }
    }
  }
])

Solution 5 - Javascript

Object.bsonsize(db.test.findOne({type:"auto"})) It gives in bytes.

Solution 6 - Javascript

Method Object.bsonsize() is available only in legacy mongo shell. In new mongosh you have to use package bson

const BSON = require("bson");

BSON.calculateObjectSize({field: "value"})

BSON.calculateObjectSize(db.test.findOne())

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1949763View Question on Stackoverflow
Solution 1 - Javascriptuser1949763View Answer on Stackoverflow
Solution 2 - JavascriptLiberateurView Answer on Stackoverflow
Solution 3 - JavascriptKonstantin YovkovView Answer on Stackoverflow
Solution 4 - JavascriptAshhView Answer on Stackoverflow
Solution 5 - JavascriptVisakh VijayanView Answer on Stackoverflow
Solution 6 - JavascriptWernfried DomscheitView Answer on Stackoverflow