How to find Schema of a Collection in MongoDB

MEAN stack is one of the most demanding collections of technologies these days. It includes MongoDB ExpressJS AngularJS and NodeJS. But whether you work on the complete stack or MongoDB alone, at some point you would want to backup & restore your database. The data that is backed up in MongoDB is usually in the form of bson/json and can be restored using commands easily available on MongoDB’s docs and platforms like StackOverflow.

While restoring and backing up data in MongoDB works like a charm, sometimes you might want to import a MongoDB backup. And to continue working on the data, you should know schemas of the collections.

If you are lucky, you will have the schema files, but if you don’t have them, you can still find out the schema of the collection using the data that resides within the collection. Let me tell you how.

We can get the schema object/first document of the collection using :

var schemaObj = db.users.findOne();

Now to print the schema, we can print out the key of each property of the schemaObj and the property’s type (e.g. string/number etc). For that, let’s write a function that takes schemaObj as input and prints the required info on console.

function printSchema(obj) {
for (var key in obj) {
print(indent, key, typeof obj[key]) ;
}
};

The above function prints out the schema and the output is:

That’s cool. Right? But it seems like “loginInfo”, “settings”, “roles” and “meta” are objects and can have several sub-properties. We might want that information too (i.e. print out nested schemas). For that, let’s improve our “printSchema” function and the function calling statement as follows:

function printSchema(obj, indent) {
for (var key in obj) {
print(indent, key, typeof obj[key]) ;
if (typeof obj[key] == "object") {
printSchema(obj[key], indent + "\t")
}
}
};
printSchema(schemaObj,"");

The above code prints the following output now:

Great! But i can see functions too in the above output. If we don’t want it, we can omit these by modifying the function a bit as follows:

function printSchema(obj, indent) {
for (var key in obj) {
if(typeof obj[key] != "function"){ //we don't want to print functions
print(indent, key, typeof obj[key], type) ;
if (typeof obj[key] == "object") { //if current property is of object type, print its sub properties too
printSchema(obj[key], indent + "\t");
}
}
}
};

Our printSchema function now gives the following output:

For advance developers: ( Since this is fun :P )

You may notice that “_created”, “_last_modified” are objects. But usually they are actually instances of Date object. Similarly, “roles” property seems like it is an Array of strings. We can get the actual data type by further modifying our printSchema function as follows:

function printSchema(obj, indent) {
for (var key in obj) {
if(typeof obj[key] != "function"){ //we don't want to print functions
var specificDataTypes=[Date,Array]; //specify the specific data types you want to check
var type ="";
for(var i in specificDataTypes){ // looping over [Date,Array]
if(obj[key] instanceof specificDataTypes[i]){ //if the current property is instance of the DataType
type = "==is_" + specificDataTypes[i].name + "=="; //get its name
break;
}
}
print(indent, key, typeof obj[key], type) ; //print to console (e.g roles object is_Array)
if (typeof obj[key] == "object") { //if current property is of object type, print its sub properties too
printSchema(obj[key], indent + "\t");
}
}
}
};
printSchema (wide-angle-view)

Below is the final output for our example of user schema:

Here it is. You can successfully extract the schema from the document of a collection in MongoDB using the above method. And it will print the complete hierarchy of the schema no matter how nested the schema is.

A sample usage after extracting schema would be the following using Mongoose in NodeJS:

var userSchema = new mongoose.Schema({
loginInfo: {
providerID: {type:String},
providerKey: {type: String}
},
firstName: {type:String},
lastName: {type:String},
fullName: {type:String},
email: {type:String},
password: {type:String},
salt: {type:String},
settings: {
preferredLang: {type: String},
isReceiveNotification: {type: Boolean},
isReceiveEmail: {type: Boolean},
},
roles: {type: Array},
status: {type: String},
meta: {
_member: {type: String},
_version: {type: Number},
_created_by: {type: String},
_created: {type: Date},
_last_modified: {type: Date},
_owner: {type: String},
_modified_by: {type: String},
}
});

Trying new technologies is always fun. Sometimes you easily get into the game but when you get stuck on a problem and can’t find a solution believe me, it’s a real PAIN. Like seriously! Cheers to everyone providing solutions for the craziest problems we face during development.