Dinoop V P
Dinoop V P

Reputation: 641

Is there any issues while creating a model when the schema is in a separated file?

Am using mongoose library inside node js. I have schema in a file, and am requiring that schema to create the model. But some times am getting the following error. but sometimes not.

"MissingSchemaError: Schema hasn't been registered for model \"data\".\nUse mongoose.model(name, schema)".

Is there any problem while requiring a schema file when creating a model? When i defined the schema structure with in the same page(apiFunctions.js), that time no errors reported. but i want this schema to be in a seperated file so that while inserting/retreving, i can just include the schema.

db.js

module.exports = require("../../db/index.js");
module.exports.schema = require("../../db/schema/registerSchema");

apiFunctions.js

var dbLib =require('./db');
var registerSchema = dbLib.schema.registerSchema; /* Path to my registerschema file. */
var profile = db.model('collection1',registerSchema);

regiserSchema.js

var mongoose = require('mongoose');
exports.registerSchema =  new mongoose.Schema( {  
    _website:{ required: true, type: String,trim: true,set: toLower ,index: {unique: true, dropDups: true }},
    user_Id:{ required: true, type: String },
    profile_id :{ required: true, type: String,index: {unique: true, dropDups: true }},
    _time: {type: Date,default: Date.now}
});
function toLower (v) {
  return v.toLowerCase();
}

index.js in /db

var mongoose = require('mongoose');
module.exports.mongoose = mongoose;
module.exports.getDb = function(dbName)
{
var dburl='mongodb://localhost/'+dbName;
    db = mongoose.createConnection( dburl, {
     server: {
     socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 }, 
     auto_reconnect:false,
     poolSize:1

     }
     },function(err){     
    console.log(err)
});
db.on('error',function(err){
console.log(err + " this is error");
db.close();
});
return db;
}

Upvotes: 1

Views: 457

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151190

You seem not to be basically understanding how the module system works in node.js. While it is true that a "require" need only be "evaluated" once, this does not automatically make things global. Therefore these lines are wrong:

var dbLib =require('./db');
var registerSchema = dbLib.schema.registerSchema;

And the reason for that is because the "db" module you have defined does not "in itself" actually export any property matching registerSchema. The "schema" property is actually something that can be referenced from the "model", once it has been defined. So one form of usage might be this:

var mongoose = require("mongoose"),
    Schema = mongoose.Schema;

var collectionSchema = new Schema({
    "_website":{ 
        "required": true,
        "type": String,
        "trim": true,
        "set": toLower ,
        "index": { "unique": true, "dropDups": true }
    },
    "user_Id": { "required": true, "type": String },
    "profile_id":{ 
        "required": true, 
        "type": String,
        "index": { "unique": true, "dropDups": true }
    },
    "_time": { "type": Date, default: Date.now }
});

function toLower (v) {
    return v.toLowerCase();
}

var Collection = mongoose.model( "Collection", collectionSchema );

console.log( Collection.schema );

And lo and behold the "schema" definition is available from the model that had that definition in scope when it was created. So you can always grab the schema from the model, and declaring them in the same place is generally the concept unless you need to "share" that schema across serveral models, and you don't want to "inspect" an existing model to get a registered schema.

So as a "multiple files" context, this would look something more like this:

"collectionSchema.js"

var mongoose = require("mongoose"),
    Schema = mongoose.Schema;

var collectionSchema = new Schema({
    "_website":{ 
        "required": true,
        "type": String,
        "trim": true,
        "set": toLower ,
        "index": { "unique": true, "dropDups": true }
    },
    "user_Id": { "required": true, "type": String },
    "profile_id":{ 
        "required": true, 
        "type": String,
        "index": { "unique": true, "dropDups": true }
    },
    "_time": { "type": Date, default: Date.now }
});

function toLower (v) {
    return v.toLowerCase();
}

module.exports = collectionSchema;

"collectionModel.js"

var mongoose = require("mongoose"),
    collectionSchema = require("./collectionSchema");

module.exports = mongoose.model( "Collection", collectionSchema );

And basically to "require" the "collectionSchema" module wherever you want to use the objects that it exports.

So this is how it works. Just because you declared something as "exported" once does not mean it appears "globaly" anywhere else you want it to. The require() will only evaluate something that was already "required" once, but you still need to do that to create a local scope in the module where you reference it.

Upvotes: 2

Related Questions