"defineCall is not a function". Using sequelize with Node.JS - node.js

I'm learning how to use Sequelize for a Node.JS project, I'm working on the models:
index.js
var Sequelize = require('sequelize');
const sequelize = new Sequelize('mysql://bf3a13a7df5b2f:e2707ede#us-cdbr-iron-east-03.cleardb.net/heroku_6bdb0d8ad6c6a50?reconnect=true');
// load models
var models = [
'student',
];
models.forEach(function(model) {
module.exports[model] = sequelize.import(__dirname + '/' + model);
});
// export connection
module.exports.student= student;
module.exports.sequelize = sequelize;
student.js
var sequelize = require('./dbConnection');
var Sequelize = require('sequelize');
const student = sequelize.define('student', {
id: {
type: Sequelize.STRING,
primaryKey: true
},
name: {
type: Sequelize.STRING
},
middleName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
},
dob: {
type: Sequelize.DATE
},
//student.sync({force: true});
});
module.exports = student;
and this is the error message I receive from the command line:
C:\Users\adria\OneDrive\Documentos\GitHub\ScholarMean1\node_modules\sequelize\lib\sequelize.js:691
this.importCache[path] = defineCall(this, DataTypes);
^
TypeError: defineCall is not a function
I managed to make it work if the model is in index.js, but because I want to make a file for each model I hope you can help me.

I saw a similar problem just now and the problem was a file that was in the models folder that was not actually a database model. Ensure that your models folder only contains models for your database. Hopefully this helps!

Related

TypeError: this.add is not a function in node js application

I have mongoose version 2.6 and mongodb version is 2.2 I am trying to make CRUD application in which I define schema. By adding Schema in my project. I am getting this error: 'TypeError: this.add is not a function'
Following is my code:
const mongoose = require('mongoose');
let userSchema = mongoose.Schema({
name: { type: String },
email: { type: String },
password: { type: String },
forgotToken: { type: String }
});
module.exports = mongoose.model('user', userSchema);
I don't know what is wrong in my code. From code model should be created without any error. Please help me out.
You forgot to create a new instance of schema object by not putting new keyword in front of it.
const mongoose = require('mongoose');
let userSchema = new mongoose.Schema({
name: { type: String },
email: { type: String },
password: { type: String },
forgotToken: { type: String }
});
module.exports = mongoose.model('user', userSchema);

Sequelize() doesn't return an instance of sequelize

I recently started using Sequelize to get a model of my postgresql database.
To map the database I am using sequelize-auto.
I was able to create an auto generated mapping of my db using sequelize-auto when I sent my arguments this way to its constructor:
init.js
let sequelizeAutoInstance = new SequelizeAuto(dbName,username,password,options)
But it doesn't work when I try to send an instance of Sequelize this way:
new-init.js
let sequelizeInstance = new Sequelize(sequelizeOptions);
sequelizeAutoInstance = new SequelizeAuto(sequelizeInstance)
Looking into sequelize-auto ctor I saw it runs those lines:
if (database instanceof Sequelize) {
this.sequelize = database;
}
but the instance returning form new Sequelize doesn't return an instance of Sequelize.
What did I miss?
thanks
If I got you correct. You need to pass an instance of sequelize to your models. If you are using extension models you can simply pass in the instance into the init options.
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = require("../your/db/file");
class User extends Model {}
User.init({
// Model attributes are defined here
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull defaults to true
}
}, {
// Other model options go here
sequelize, // We need to pass the connection instance
modelName: 'User' // We need to choose the model name
});
if its functional then
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = require("../your/db/file");
const User = sequelize.define('User', {
// Model attributes are defined here
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull defaults to true
}
}, {
// Other model options go here
});
All this can be found in the Sequelize models documentation

sequelize .create is not a function error

I'm getting Unhandled rejection TypeError: feed.create is not a function error and I can't understand why it occurs. What's the problem here?
Here's my code. I'm probably not doing something very fundamental here since I can't reach feed variable in routes/index.js.
If I add module.exports = feed; to my models file, I can reach it, but I have more than one models, so if I add additional models below the feed, they override it.
db.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize('mydatabase', 'root', 'root', {
host: 'localhost',
dialect: 'mysql',
port: 8889,
pool: {
max: 5,
min: 0,
idle: 10000
},
define: {
timestamps: false
}
});
var db = {};
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
models.js
var db = require('./db'),
sequelize = db.sequelize,
Sequelize = db.Sequelize;
var feed = sequelize.define('feeds', {
subscriber_id: Sequelize.INTEGER,
activity_id: Sequelize.INTEGER
},
{
tableName: 'feeds',
freezeTableName: true
});
routes/index.js
var express = require('express');
var router = express.Router();
var models = require('../models');
router.get('/addfeed', function(req,res) {
sequelize.sync().then(function () {
return feed.create({
subscriber_id: 5008,
activity_id : 116
});
}).then(function (jane) {
res.sendStatus(jane);
});
});
You cannot reach a variable from a file, by only requiring it in another one. You need to either define an object literal to hold all your variables in one place and assign it to module.exports, or you need to import them from different files separately.
In your case, I would create separate files to hold table schemas, and then import them by sequelize.import under one file, then require that file.
Like this:
models/index.js:
var sequelize = new Sequelize('DBNAME', 'root', 'root', {
host: "localhost",
dialect: 'sqlite',
pool:{
max: 5,
min: 0,
idle: 10000
},
storage: "SOME_DB_PATH"
});
// load models
var models = [
'Users',
];
models.forEach(function(model) {
module.exports[model] = sequelize.import(__dirname + '/' + model);
});
models/Users.js
var Sequelize = require("sequelize");
module.exports=function(sequelize, DataTypes){
return Users = sequelize.define("Users", {
id: {
type: DataTypes.INTEGER,
field: "id",
autoIncrement: !0,
primaryKey: !0
},
firstName: {
type: DataTypes.STRING,
field: "first_name"
},
lastName: {
type: DataTypes.STRING,
field: "last_name"
},
}, {
freezeTableName: true, // Model tableName will be the same as the model name
classMethods:{
}
},
instanceMethods:{
}
}
});
};
Then import each model like this:
var Users = require("MODELS_FOLDER_PATH").Users;
Hope this helps.
Just use
const { User } = require("../models");
Update :
in newer version of sequelize v6 and beyond sequelize.import is deprecated
sequelize docs recommend using require now
If you have generated models using migrations
this is how your model file will look like
models/user.js
'use strict'
module.exports = (sequelize, DataTypes, Model) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
User.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
phone_number: {
type: DataTypes.STRING(20)
},
otp: {
type: DataTypes.INTEGER(4).UNSIGNED
},{
sequelize,
modelName: 'User',
});
return User;
};
as you can see your model export function has sequelize DataTypes & Model parameters.
so when you import this model you should send above arguments.
Example
I am importing user model in controllers/user.js file, it could be any file
controllers/controller.js
const Sequelize = require('sequelize');
const sequelize = require('../config/db').sequelize;
// Bring in Model
const User = require('../models/user')(sequelize, Sequelize.DataTypes,
Sequelize.Model);
// your code...
// User.create(), User.find() whatever
Notice that sequelize(with small 's') and Sequelize(with capital 'S') are different things, first one represent instance of Sequelize created using new Sequelize, second one is just package you installed & imported
first one (sequelize) can be found wherever you started a connection to database using const sequelize = new Sequelize() usually from app.js or db.js file, make sure to export it from there and import it into where you want to use Model i.e controller
export sequelize instance
db.js Or app.js
const sequelize = new Sequelize();
... //your code
...
module.exports = {
sequelize: sequelize
}
You may want to check the answer given on the link below tackling the same issue, I was able to resolve mine using const User = sequelize.import('../models/users');, instead of just import User from '../models/users';
Sequelize create not a function?
I came with the same issue when I used something like:
const { Feed } = require("../models/Feed.js");
So, just using the code down below solved it
const { Feed } = require("../models");

Nodejs with Sequelizejs using separate files per model

This is an embarrassingly beginner question, but I just want to settle my worries about Sequelizejs. I want to split out each model into its own file to keep my source organized. In order to do that I need to require("sequelize') and var sequelize = new Sequelize('DB-Name', 'DB-User', 'DB-Password'); at the start of each file.
My question is, will that create a new connection to the database per model, or will it just keep re-using the same connection? Should I abandon the whole concept of "one model per file" and just create a master Models.js file?
I am very new to Node and am still getting used to its conventions. Thanks for the help!
Every model is defined as its own module, which you export:
module.exports = function(sequelize, DataTypes){
return sequelize.define('Brand', {
name: {
type: DataTypes.STRING,
unique: true,
allowNull: false },
description: {
type: DataTypes.TEXT,
allowNull: false },
status: {
type: DataTypes.INTEGER,
unique: false,
allowNull: true }
})
};
Then simply import the module when you initialize Sequelize (and you can import many models here):
var Sequelize = require("sequelize");
var config = require("../../config/config.js");
var sequelize = new Sequelize(config.database, config.username, config.password,
{ dialect: config.dialect, host: config.host, port: config.port,
omitNull: true, logging: false });
var Brand = require("./Brand").Brand;
You can read up more on modules at http://nodejs.org/api/modules.htm but the example above should get you started.
In case if one wants to use EcmaScript 6 approach there is great example with explanation in Sequelize documentation here.
// in your server file - e.g. app.js
const Project = sequelize.import(__dirname + "/path/to/models/project")
// The model definition is done in /path/to/models/project.js
// As you might notice, the DataTypes are the very same as explained above
module.exports = (sequelize, DataTypes) => {
return sequelize.define("project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
}
The import method can also accept a callback as an argument.
sequelize.import('project', (sequelize, DataTypes) => {
return sequelize.define("project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
})

File Structure of Mongoose & NodeJS Project

I currently have all my models (Schema definitions) in the /models/models.js file for my Mongoose/NodeJS application.
I'd like to break these apart into different files as such: user_account.js, profile.js, etc. However I cannot seem to do so as my controllers break and report back "cannot find module" once I pull these classes apart.
My project structure is as follows:
/MyProject
/controllers
user.js
foo.js
bar.js
// ... etc, etc
/models
models.js
server.js
The contents of my models.js file looks like this:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
mongoose.connect('mongodb://localhost/mydb');
var UserAccount = new Schema({
user_name : { type: String, required: true, lowercase: true, trim: true, index: { unique: true } },
password : { type: String, required: true },
date_created : { type: Date, required: true, default: Date.now }
});
var Product = new Schema({
upc : { type: String, required: true, index: { unique: true } },
description : { type: String, trim: true },
size_weight : { type: String, trim: true }
});
My user.js file (controller) looks like this:
var mongoose = require('mongoose'),
UserAccount = mongoose.model('user_account', UserAccount);
exports.create = function(req, res, next) {
var username = req.body.username;
var password = req.body.password;
// Do epic sh...what?! :)
}
How can I break the schema definition into multiple files and also reference it from my controller? When I do reference it (after the schema is in a new file) I get this error:
*Error: Schema hasn't been registered for model "user_account".*
Thoughts?
Here's a sample app/models/item.js
var mongoose = require("mongoose");
var ItemSchema = new mongoose.Schema({
name: {
type: String,
index: true
},
equipped: Boolean,
owner_id: {
type: mongoose.Schema.Types.ObjectId,
index: true
},
room_id: {
type: mongoose.Schema.Types.ObjectId,
index: true
}
});
var Item = mongoose.model('Item', ItemSchema);
module.exports = {
Item: Item
}
To load this from an item controller in app/controllers/items.js I would do
var Item = require("../models/item").Item;
//Now you can do Item.find, Item.update, etc
In other words, define both the schema and the model in your model module and then export just the model. Load your model modules into your controller modules using relative require paths.
To make the connection, handle that early in your server startup code (server.js or whatever). Usually you'll want to read the connection parameters either from a configuration file or from environment variables and default to development mode localhost if no configuration is provided.
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost');
A couple answers here really helped me develop an alternative approach. The original question is regarding breaking just the Schema definition out, but I prefer to bundle the Schema and Model definitions in the same file.
This is mostly Peter's idea, only exporting the model definition by overriding module.exports to make accessing the model from your controller a little less verbose:
Project layout:
MyProject
/controllers
user.js
foo.js
bar.js
// ... etc, etc
/models
Item.js
server.js
models/Item.js would look like:
var mongoose = require("mongoose");
var ItemSchema = new mongoose.Schema({
name: {
type: String,
index: true
}
});
module.exports = mongoose.model('Item', ItemSchema);
// Now `require('Item.js')` will return a mongoose Model,
// without needing to do require('Item.js').Item
And you access the model in a controller, say user.js, like:
var Item = require(__dirname+'/../models/Item')
...
var item = new Item({name:'Foobar'});
Don't forget to call mongoose.connect(..) in server.js, or wherever else you deem appropriate!
I recently answered a Quora question with regard to this same problem.
http://qr.ae/RoCld1
What I have found very nice and saves on the amount of require calls is to structure your models into a single directory. Make sure you only have a single model per file.
Create an index.js file in the same directory as your models. Add this code to it. Be sure to add the necessary fs require
var fs = require('fs');
/*
* initializes all models and sources them as .model-name
*/
fs.readdirSync(__dirname).forEach(function(file) {
if (file !== 'index.js') {
var moduleName = file.split('.')[0];
exports[moduleName] = require('./' + moduleName);
}
});
Now you can call all your models as follows:
var models = require('./path/to/models');
var User = models.user;
var OtherModel = models['other-model'];
Peter Lyons pretty much covered the basis.
Borrowing from the above example (removing the lines after the schema) I just wanted to add:
app/models/item.js
note: notice where `module.exports` is placed
var mongoose = require("mongoose");
var ItemSchema = module.exports = new mongoose.Schema({
name: {
type: String,
index: true
},
...
});
To load it from the app/controllers/items.js
var mongoose = require('mongoose');
var Item = mongoose.model('Item', require('../models/item'));
Another way without the module.exports or require:
app/models/item.js
var mongoose = require("mongoose");
var ItemSchema = new mongoose.Schema({
name: {
type: String,
index: true
},
...
});
mongoose.model('Item', ItemSchema); // register model
In the app/controllers/items.js
var mongoose = require('mongoose')
, Item = mongoose.model('Item'); // registered model
Inspired by sequelize-cli, I have a models directory where i define all schema.
Complete app on github: https://github.com/varunon9/node-starter-app-mongo
models/index.js-
'use strict';
const fs = require('fs');
const path = require('path');
const mongoose = require('mongoose');//.set('debug', true);
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
const Schema = mongoose.Schema;
fs
.readdirSync(__dirname)
.filter(fileName => {
return (
fileName.indexOf('.') !== 0)
&& (fileName !== basename)
&& (fileName.slice(-3) === '.js'
);
})
.forEach(fileName => {
const model = require(path.join(__dirname, fileName));
const modelSchema = new Schema(model.schema);
modelSchema.methods = model.methods;
modelSchema.statics = model.statics;
// user.js will be user now
fileName = fileName.split('.')[0];
db[fileName] = mongoose.model(fileName, modelSchema);
});
module.exports = db;
models/user.js-
'use strict';
module.exports = {
schema: {
email: {
type: String,
required: true,
unique: true,
},
mobile: {
type: String,
required: false
},
name: {
type: String,
required: false
},
gender: {
type: String,
required: false,
default: 'male'
},
password: {
type: String,
required: true
},
dob: {
type: Date,
required: false
},
deactivated: {
type: Boolean,
required: false,
default: false
},
type: {
type: String,
required: false
}
},
// instance methods goes here
methods: {
},
// statics methods goes here
statics: {
}
};
I like using classes to organize everything, maybe try this:
const mongoose = require('mongoose')
class UserAccount {
constructor() {
this.schema = new mongoose.Schema({
user_name: { type: String, required: true, lowercase: true, trim: true, index: { unique: true } },
password: { type: String, required: true },
date_created: { type: Date, required: true, default: Date.now }
});
this.model = new mongoose.model('UserAccount', this.schema)
}
create = (obj) => {
return new Promise((resolve, reject) => {
this.model.create({ ...item })
.then((result) => {
resolve(result)
}).catch((err) => {
reject(err)
});
});
}
}
module.exports = UserAccount;
This approach allows you to add custom methods. Plus it combines the controller/model into a single vector, allowing you to detach the model at any time. This may not scale in enterprise, but it may suite smaller apps.

Resources