-
-
Save joeyAghion/6511184 to your computer and use it in GitHub Desktop.
var collectionNames = db.getCollectionNames(), stats = []; | |
collectionNames.forEach(function (n) { stats.push(db[n].stats()); }); | |
stats = stats.sort(function(a, b) { return b['size'] - a['size']; }); | |
for (var c in stats) { print(stats[c]['ns'] + ": " + stats[c]['size'] + " (" + stats[c]['storageSize'] + ")"); } |
Improved how to get the collection:
function getReadableFileSizeString(fileSizeInBytes) {
var i = -1;
var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
do {
fileSizeInBytes = fileSizeInBytes / 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
};
var collectionNames = db.getCollectionNames(), stats = [];
collectionNames.forEach(function (n) { stats.push(db.getCollection(n).stats()); });
stats = stats.sort(function(a, b) { return b['size'] - a['size']; });
for (var c in stats) { print(stats[c]['ns'] + ": " + getReadableFileSizeString(stats[c]['size']) + " (" + getReadableFileSizeString(stats[c]['storageSize']) + ")"); }
Hi Guys,
This script really helps, thanks a lot. I'm a mongodb DBA; pretty new to java script. Can you suggest me something to improve my java-script skills (Especially for mongoDB). I need to write my own scripts like this. Also can you explain me the above script, how it works? Thanks for a lot
Regards
Albert
Hi @levay1, the script provided by lattmann does the following:
- Defines a function called "getReadableFileSizeString" that converts a number of bytes to a more human readable string.
- Then gest all collection names in "collectionNames" variable.
- Get the stats for all collections and stores them in the array variable "stats"
- Sorts the stats by size
- Finally traverse all the stats and prints the Namespace and both sizes (size and storageSize)
If you would like to improve your javascript skills, there are tons of material, here are a few:
I took @lattmann's human readable version and made a loop of all the databases.
var mgo = new Mongo()
function getReadableFileSizeString(fileSizeInBytes) {
var i = -1;
var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
do {
fileSizeInBytes = fileSizeInBytes / 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
};
function getStatsFor(db){
var collectionNames = db.getCollectionNames(), stats = [];
collectionNames.forEach(function (n) { stats.push(db.getCollection(n).stats()); });
stats = stats.sort(function(a, b) { return b['size'] - a['size']; });
for (var c in stats) { print(stats[c]['ns'] + ": " + getReadableFileSizeString(stats[c]['size']) + " (" + getReadableFileSizeString(stats[c]['storageSize']) + ")"); }
}
function getAllStats(){
mgo.getDBNames().forEach(function(name){ var db = mgo.getDB(name); print('\n '+db+'\n'); getStatsFor(db) })
}
getAllStats()
With these functions you can get stats for the current (use
) DB with a simple getStatsFor(db)
call, or get stats for a named DB with getStatsFor(mgo.getDB('db_name'))
This will actually fail if mongo is not running on 27017, or if it's configured to use SSL, and so on.
The first line should be changed like this:
var mgo = db.getMongo()
reworked abit @RichardBronosky 's code to include indexes stats
var mgo = new Mongo()
function getReadableFileSizeString(fileSizeInBytes) {
var i = -1;
var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
do {
fileSizeInBytes = fileSizeInBytes / 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
};
function getStatsFor(db){
var collectionNames = db.getCollectionNames(), stats = [];
collectionNames.forEach(function (n) { stats.push(db.getCollection(n).stats()); });
stats = stats.sort(function(a, b) { return b['size'] - a['size']; });
for (var c in stats) {
print(stats[c]['ns'] + ": " + getReadableFileSizeString(stats[c]['size']) + " (" + getReadableFileSizeString(stats[c]['storageSize']) + ")");
for (var i in stats[c]['indexSizes']){ print(" idx:" + i + ":" + getReadableFileSizeString(stats[c]['indexSizes'][i]) );}
}
}
function getAllStats(){
mgo.getDBNames().forEach(function(name){ var db = mgo.getDB(name); print('\n '+db+'\n'); getStatsFor(db) })
}
getAllStats()
Wanna ask something, how to use this script with authentication enable. because i got error message like this:
"errmsg" : "not authorized on admin to execute command { listDatabases: 1.0, $db: \"admin\" }",
Thank you,
More readable including index and collection document counts
var mgo = new Mongo()
function getReadableFileSizeString(fileSizeInBytes) {
var i = -1;
var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
do {
fileSizeInBytes = fileSizeInBytes / 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
};
function getStatsFor(db){
var collectionNames = db.getCollectionNames(), stats = [];
collectionNames.forEach(function (n) { stats.push(db.getCollection(n).stats());});
stats = stats.sort(function(a, b) { return b['size'] - a['size']; });
for (var c in stats) {
print(
"collectionName" +":"+ stats[c]['ns'] +"-"+
"documentCount" +":"+ stats[c]['count'] +"-"+
"indexesCount" +":"+ stats[c]['nindexes'] +"-"+
"totalIndexSize" +":"+ getReadableFileSizeString(stats[c]['totalIndexSize']) +"-"+
"size" +":"+ getReadableFileSizeString(stats[c]['size']) +"-"+
"storageSize" +":"+ getReadableFileSizeString(stats[c]['storageSize']) );
for (var i in stats[c]['indexSizes']){ print(" idx:" + i + ":" + getReadableFileSizeString(stats[c]['indexSizes'][i]) );}
}
}
function getAllStats(){
mgo.getDBNames().forEach(function(name){ var db = mgo.getDB(name); print('\n '+db+'\n'); getStatsFor(db) })
}
getAllStats()
thanks for this awesome script and the updates!
I have incorporated most of the above, added output customizations (include/exclude index, sorting order, long/short format)
feel free to check it out my gist
EDIT: added small improvement to getReadableFileSizeString
. It now accepts number of decimal places, and truncate extra zeros from the number (just by casting to a Number
before printing).
You can write a more 'elegant' version:
function getCollectionSizes() {
db.getCollectionNames().map(function(name) {
return {"name":name, "size": db.getCollection(name).stats()["size"] || 0};
}).sort(function(a, b) {
return b["size"] - a["size"];
}).forEach(function(x) {
// MongoDB JavaScript Engine does not support string.padEnd
let pad = " ";
print(x.name + pad.slice(0, Math.max(16 - x.name.length, 0)) + ":\t" + x.size);
});
}
getCollectionSizes();
If you're using a newer version of mongo which supports ES6 this is a more terse form of the above with information about the index sizes and uses 3 decimal places like show dbs
does from the mongo shell
const readableSize = (size) => {
const scale = (Math.log(size) / Math.log(1024)) | 0;
return (size / Math.pow(1024, scale)).toFixed(3) + ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][scale];
}
const printStats = (mongo) => {
mongo.getDBNames()
.map((i) => mongo.getDB(i))
.forEach((db) => {
print(db);
print(Array(81).join('='));
db.getCollectionNames()
.map((i) => db.getCollection(i).stats())
.sort((a, b) => b.size - a.size)
.forEach((s) => {
print(`${s.ns}: ${readableSize(s.size)} (${readableSize(s.storageSize)})`);
print(`Indexes: (${readableSize(s.totalIndexSize)})`);
Object.entries({...s.indexSizes}).sort((a, b) => b[1] - a[1]).forEach(([n, s]) => {
print(` ${n}: ${readableSize(s)}`);
});
print('');
});
print('');
});
}
// and used:
printStats(db.getMongo())
which would render:
admin
================================================================================
admin.system.users: 4.284kB (36.000kB)
Indexes: (72.000kB)
_id_: 36.000kB
user_1_db_1: 36.000kB
admin.system.keys: 425.000B (36.000kB)
Indexes: (36.000kB)
_id_: 36.000kB
admin.system.version: 104.000B (36.000kB)
Indexes: (32.000kB)
_id_: 32.000kB
config
================================================================================
config.system.sessions: 41.995MB (9.809MB)
Indexes: (38.055MB)
_id_: 36.574MB
lsidTTLIndex: 1.480MB
config.transactions: 304.604kB (204.000kB)
Indexes: (1.250MB)
_id_: 1.250MB
Try this to get all DBs, collections and document count:
mongo --eval " db.getMongo().getDBNames().forEach( function(v, i){ db.getSiblingDB(v).getCollectionNames().forEach( function(vv, ii){ print (v + ',' + vv + ',' + db.getSiblingDB(v).getCollection(vv).count() ) } ) } ) "
Is there a way to then store this data in a collection as historical data . To monitor collection size growth over a period of time
@nenohweg something like datadog?
Also here's a version which works better for me - the versions at the top of this thread *** will silently omit values as they error on system.profile
***
(function() {
const byteUnits = [" kB", " MB", " GB", " TB", "PB", "EB", "ZB", "YB"];
// get collections by size sorted
function getReadableFileSizeString(fileSizeInBytes) {
let i = -1;
do {
fileSizeInBytes = fileSizeInBytes / 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
}
const collectionNames = db.getCollectionNames();
let stats = [];
for (const name of collectionNames) {
if (name === 'system.profile') {
continue;
}
stats.push(db.getCollection(name).stats());
}
stats = stats.sort(function(a, b) {
return b["size"] - a["size"];
});
for (let i = 0; i < stats.length; i++) {
console.log(stats[i]["ns"] + ": " + getReadableFileSizeString(stats[i]["size"]) + " (" + getReadableFileSizeString(stats[i]["storageSize"]) + ") - ", Number(stats[i].count).toLocaleString(), " docs");
}
})();
Also includes formatted doc count.
I started with the version from terencehonles, but ran into errors when encountering views. So, I added a filter after getting the collection names to inspect the type to verify it is a collection before calling stats()
.
const readableSize = (size) => {
const scale = (Math.log(size) / Math.log(1024)) | 0;
return (size / Math.pow(1024, scale)).toFixed(3) + ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][scale];
}
const printStats = (mongo) => {
mongo.getDBNames()
.map((i) => mongo.getDB(i))
.forEach((db) => {
print(db);
print(Array(81).join('='));
db.getCollectionNames()
.filter((i) => (db.getCollection(i).exists() !== null && db.getCollection(i).exists().type === 'collection'))
.map((i) => db.getCollection(i).stats())
.sort((a, b) => b.size - a.size)
.forEach((s) => {
print(`${s.ns}: ${readableSize(s.size)} (${readableSize(s.storageSize)})`);
print(`Indexes: (${readableSize(s.totalIndexSize)})`);
Object.entries({...s.indexSizes}).sort((a, b) => b[1] - a[1]).forEach(([n, s]) => {
print(` ${n}: ${readableSize(s)}`);
});
print('');
});
print('');
});
}
// and used:
printStats(db.getMongo())
Nice gist, thanks! I tweaked it slightly using a human-readable storage size function from StackOverflow: