how to import modules that require arguments - node.js

this is my files sturcture:
-models
-user.js
-room.js
-database.js
-controllers
-createRoom.js
-routes.js
..
user.js and room.js are modules i want to import in database.js. right now im doing like this:
in database.js:
var mysql = require('mysql');
var Sequelize = require('sequelize');
var db = new Sequelize('test', 'root', 'root', {
dialect: "mysql",
port: 3306
})
var User = require('./user.js')(Sequelize, db);
var Room = require('./room.js')(Sequelize, db);
module.exports = function(){
//code...
};
in user.js/room.js
module.exports = function (Sequelize, db) {
var Room = db.define('Room', {
room_id : {type: Sequelize.INTEGER, allowNull: false, autoIncrement: true, primaryKey: true},
})
db
.sync({force: true})
.complete(function (err) {})
so far so good, but when i need to import user.js or room.js in other files besides database.js(eg, createRoom.js), i have trouble importing them because theres no Sequelize and db defined like in the database.js. does it mean i have to connect to the database and require Sequelize again whenever i need to use user.js and room.js module in other files? is there a better way to work around this?? thanks!

you have different possibilities here
re-export models:
in your database.js
//init code as seen
module.exports.Room = Room
importing somewhere else
require('../models/database').Room
make your database.js dependency
in database.js
module.export = { Sequelize: Sequelize, db : db}
in room.js
var dbModule = require('./database')
module.exports = dbModule.Sequelize.define('Room', /*....*/)
Attach the model to the init function
in room.js
module.exports = roomInit
function roomInit(Sequelize, db) {
roomInit.Room = db.define('Room', {
room_id : {type: Sequelize.INTEGER, allowNull: false, autoIncrement: true, primaryKey: true}
})
db
.sync({force: true})
.complete(function (err) {})
}
usage
require('./room').Room

Related

Sequelize OP -> TypeError: Cannot read property 'like' of undefined

In my project, i'd like to search many subways have a certain keyword.
So, I use Op in Sequelize, but it returned TypeError: Cannot read property 'like' of undefined.
The way I initialized the sequelize object is as follows.
// root/models/index.js
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
module.exports = db;
And, I initialized and used the Op object like this
const { Subway } = require("../../models");
const sequelize = require("../../models").sequelize;
const Op = sequelize.Op;
const list = await Subway.findAll({
where: {
station_name_kr: {
[Op.like]: '%' + req.params.filter + '%',
},
},
attributes: [
'idx',
'station_line',
'station_name_kr'
],
});
But it didn't work....
Could you tell me what is the problem?
Edit 1
// models/subway.js
const Sequelize = require('sequelize');
module.exports = class Subway extends Sequelize.Model {
static init(sequelize){
return super.init({
idx: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
station_code: {
type: Sequelize.CHAR(20),
},
station_name_kr: {
type: Sequelize.CHAR(20),
allowNull: false,
},
station_name_en: {
type: Sequelize.CHAR(30),
},
station_line: {
type: Sequelize.CHAR(10),
},
outside_code: {
type: Sequelize.CHAR(10),
},
}, {
sequelize,
timestamps: true,
underscored: true,
paranoid: true,
modelName: 'subway',
tableName: 'Subway',
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
};
The problem in your code is that you are mistaking two things.
First one:
Sequelize object from requiring library.
Second one:
sequelize connection from "instantiating" the Sequelize Object.
Note the upper case and lower case (s)(S)equelize because they represent two distinct objects.
Below what you are trying to do is access the connection and from there the Operator (Op) property. It is not going to work. The sequelize connection does NOT have it.
const sequelize = require("../../models").sequelize;
const Op = sequelize.Op;
To be able to access you should do the following:
const Sequelize = require('sequelize');
const Op = sequelize.Op;
That is why your answer "works". But that answer is not why it works.
Oh the answer was very simple...
I just initialize a Op object like this.
const Op = require("sequelize").Op;
Then, I could use the Op object with like, or , and etc...

"defineCall is not a function". Using sequelize with 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!

How to modulize my mongoose setup

This use of db.model('Model_Name').find(...) worked before, but I've since split my database, model and controllers up, so now it seems I need to change things around Please help show where I'm going wrong:
schema.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var UsersSchema = new Schema({
display_name : String,
email : String
});
var ClientErrorsSchema = new Schema({
datetime : Number,
msg : String,
url : String,
line : Number
});
var users = mongoose.model('Users',UsersSchema);
var client_errors = mongoose.model('Client_Errors',ClientErrorsSchema);
module.exports = mongoose.model;
db.js
var mongoose = require('mongoose');
var model = require("./schema.js");
var MONGO = {
username: "admin",
password: "***",
server: 'localhost',
port: '*****',
db: 'db_name',
connectionString: function(){
return 'mongodb://'+this.username+':'+this.password+'#'+this.server+'/'+this.db;
},
options: {
server:{
auto_reconnect: true,
poolSize: 20,
socketOptions:{
keepAlive: 1
}
},
db: {
numberOfRetries: 10,
retryMiliSeconds: 1000
}
}
};
var db = mongoose.createConnection(MONGO.connectionString(), MONGO.options);
db.model = model;
db.on('error', function(err) {
f.consoleLogger("DB connection Error: "+err);
});
db.on('open', function() {
f.consoleLogger("DB connected");
});
db.on('close', function(str) {
f.consoleLogger("DB disconnected: "+str);
});
module.exports = db;
user.js
var db = require("./db.js");
...
db.model('Users').find(...)
So using the util.inspect, I can see the db has all of the models, but the error I'm getting on the find is TypeError: Cannot read property 'User' of undefined'.
UPDATE
Toad22222 provided great advice, and the schema appears to be valid - but the queries are not working - neither db.model.Users.find({...},function(err,data){...}); or db.model.Users.find({...}).exec(function(err,data){...}); fires the callback. I have put the same code in the on('open') event as well, nothing happens. Hopefully someone can explain why.
All advice appreciated!
Try out
module.exports = {
User: users,
ClientErrors: client_errors
}
instead of
module.exports = mongoose.model;
You want to be exporting the schemas you are creating, not the mongoose.model datatype.

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
})
})

Resources