How to deal with require-loops? - node.js

I have two models defined like this:
user.js
var sequelize = require('../database.js').sequelize,
Sequelize = require('../database.js').Sequelize,
userAttributes = require('./userAttributes.js');
User = sequelize.define('user', {},{
classMethods: {
createRider: function(params) {
var reqs = ['name', 'phone', 'fbprofile'],
values = [],
newUser;
reqs.forEach((req) => {
var value = params[req];
});
//Here I want to use the userAttributes-object.
return newUser;
}
}
});
module.exports = User;
userAttributes.js
var sequelize = require('../database.js').sequelize,
Sequelize = require('../database.js').Sequelize,
User = require('./user.js');
UserAttribute = sequelize.define('userAttributes', {
name: Sequelize.STRING,
value: Sequelize.STRING,
});
UserAttribute.belongsTo(User);
module.exports = UserAttribute;
in user User.addRider I want to add some records to UserAttributes, so I want to inclued that model in user. In userAttributes, I need to require Users to define it as a belongsTo. This doesn't seem to work. How can I solve this?

You can use a single file which imports all models and associates them after all models have been imported. This way, you do not need any circular references.
The second most popular answer in this question describes how to do it: How to organize a node app that uses sequelize?.

Related

create dynamically mongo collection in mongoose

create dynamically mongo collection in mongoose. I tried below code: suggest me please
function residenceModel(regionName){
const residenceSchema = new Schema({
key:String,
value:String
}, { strict: false });
return mongoose.model(
`residence_meta_${regionName}`,
residenceSchema,
`residence_meta_${regionName}`
);
}
console.log(residenceModel);
exports.ResidenceModel = residenceModel;
You can create dynamic model with this simple steps
create a file dynamicModel.js
const mongoose = require('mongoose')
//import mongoose from 'mongoose'
const Schema = mongoose.Schema
const dynamicModel = (regionName) => {
const residenceSchema = new Schema({
key:String,
value:String
}, { strict: false })
return mongoose.model(
`residence_meta_${regionName}`,
residenceSchema,
`residence_meta_${regionName}`
);
}
module.exports = { dynamicModel }
// export default { dynamicModel }
On file where you want to include or create model let's say app.js
// Please take care of path
const { dynamicModel } = require("./dynamicModel")
//import { dynamicModel } from "./dynamicModel";
.....
.....
// User this method to create model and use It
const countryModel = dynamicModel("country")
countryModel.create({ key:"country", value:"USA" });
Use this method multiple time, Give it a shot and let me know
I fixed this issue. below is the code. you guys can use it.
function createMetaCollection(regionName){
console.log(regionName);
var residenceSchema = new Schema({
region:String,
customer_type:String,
},{strict: false});
residenceSchema.plugin(autoIncrement.plugin,{model:'resident_meta_'+regionName,field:regionName+'id',startAt:1});
exports.Typeof_employment_meta = mongoose.model('resident_meta_'+regionName,residenceSchema,'resident_meta_'+regionName);
}

How to implement more than one collection in get() function?

My model university.js
const mongoose = require('mongoose');
const UniversitySchema = mongoose.Schema({
worldranking:String,
countryranking:String,
universityname:String,
bachelorprogram:String,
masterprogram:String,
phdprogram:String,
country:String
},{collection:'us'});
const University =module.exports = mongoose.model('University',UniversitySchema);
My route.js
const express = require('express');
const router = express.Router();
const University = require('../models/university');
//retrieving data
//router.get('/universities',(req,res,next)=>{
// University.find(function(err,universities){
// if(err)
// {
// res.json(err);
//}
// res.json(universities);
//});
//});
router.get('/usa',function(req,res,next){
University.find()
.then(function(doc){
res.json({universities:doc});
});
});
module.exports= router;
How to implement multiple collections in this get() function? I put my collection name in the model. Please help me with a solution to call multiple collections in get() function.
Here is Example to use multiple collection names for one schema:
const coordinateSchema = new Schema({
lat: String,
longt: String,
name: String
}, {collection: 'WeatherCollection'});
const windSchema = new Schema({
windGust: String,
windDirection: String,
windSpeed: String
}, {collection: 'WeatherCollection'});
//Then define discriminator field for schemas:
const baseOptions = {
discriminatorKey: '__type',
collection: 'WeatherCollection'
};
//Define base model, then define other model objects based on this model:
const Base = mongoose.model('Base', new Schema({}, baseOptions));
const CoordinateModel = Base.discriminator('CoordinateModel', coordinateSchema);
const WindModel = Base.discriminator('WindModel', windSchema);
//Query normally and you get result of specific schema you are querying:
mongoose.model('CoordinateModel').find({}).then((a)=>console.log(a));
In Short,
In mongoose you can do something like this:
var users = mongoose.model('User', loginUserSchema, 'users');
var registerUser = mongoose.model('Registered', registerUserSchema, 'users');
This two schemas will save on the 'users' collection.
For more information you can refer to the documentation: http://mongoosejs.com/docs/api.html#index_Mongoose-model or you can see the following gist it might help.
Hope this may help you. You need to modify according to your requirements.

How to get model from sequelize.model after use sequelize-cli

I use sequelize-cli to auto generate code for model Student:
module.exports = (sequelize, DataTypes) => {
var _stu = sequelize.define('stu', {
name: DataTypes.STRING,
password: DataTypes.STRING,
gender: DataTypes.INTEGER,
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
}
}
});
return _stu
};
My question are
How to get model named stu? As the sequelize is defined in function signature.
When sequelize model:generate,sequelize read config in config.json,where dbname,passowrd are specified.
How the sequelize in the function signature knows database connection config,say,name,password,etc as I don't specify in this js file.
Answer for question 1:
"sequelize.import" will do this job.
Try this code:
const Sequelize = require('sequelize')
const sequelize = new Sequelize(...)
const stu = sequelize.import('./models/stu')
stu.findAll.then(...)
When you generate models via the CLI, it creates a handy models/index.js file that handles passing in a Sequelize instance for you. You can simply require cherry picked, existing models via ES6 destructuring like this:
var { stu } = require("./models");
stu.findAll().then(...);
Alternatively, you could require them all at once, and then access specific models as needed:
var models = require("./models");
models.stu.findAll().then(...);
The way i make it works was importing model with the require() function and then call it with required parameters.
Explanation
By require function you will get another function that returns your model.
module.exports = (sequelize, DataTypes) => {
const stu = sequelize.define('stu', {
// ...database fields
}, {});
stu.associate = function(models) {
// associations can be defined here
};
return sty;
} // note that module.exports is a function
Now, this function requires the initialized sequelize object and a DataTypes object, so you just have to pass the instance of sequelize and Sequelize.DataTypes and then it will return your model, example:
const Sequelize = require('sequelize');
const sequelize = new Sequelize(...);
const Stu = require('./models/stu')(sequelize, Sequelize.DataTypes);
Finally you can get your database rows with Stu.findAll().
Hope this can help you.

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");

Sequelize: Require vs Import

In the documentation for sequlize they use the import function like so
// in your server file - e.g. app.js
var 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 = function(sequelize, DataTypes) {
return sequelize.define("Project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
}
However, what would be so wrong with this?
// in your server file - e.g. app.js
var Project = require(__dirname + "/path/to/models/project")
// The model definition is done in /path/to/models/project.js
var Project = sequelize.define("Project", {
name: Sequelize.STRING,
description: Sequelize.TEXT
});
module.exports = Project
Well, as you can see your model definition needs two things:
Sequelize or DataTypes
sequelize
In your first example when using sequelize.import('something'); it is similar to use require('something')(this, Sequelize); (this being the sequelize instance)
Both are necessary to initialize your model, but the important thing to understand is: One of these is a classtype so it's global, the other one is an instance and has to be created with your connection parameters.
So if you do this:
var Project = sequelize.define("Project", {
name: Sequelize.STRING,
description: Sequelize.TEXT
});
module.exports = Project
Where does sequelize come from? It has to be instantiated and passed somehow.
Here is an example with require instead of import:
// /path/to/app.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize(/* ... */);
var Project = require('/path/to/models/project')(sequelize, Sequelize);
// /path/to/models/project.js
module.exports = function (sequelize, DataTypes) {
sequelize.define("Project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
});
};
module.exports = Project
You could even change it so you wouldn't have to pass Sequelize by requiring it in the model itself, but you would still need to create a sequelize instance prior to define the model.
sequelize.import is deprecated as of sequelize 6
As mentioned at https://sequelize.org/master/manual/models-definition.html
Deprecated: sequelize.import
Note: You should not use sequelize.import. Please just use require instead.
So you should just port:
// index.js
const sequelize = new Sequelize(...)
const User = sequelize.import('./user')
// user.js
module.exports = (sequelize, DataTypes) => {
// Define User.
return User;
}
to:
// index.js
const sequelize = new Sequelize(...)
const User = require('./user')(sequelize)
// user.js
const { DataTypes } = require('sequelize')
module.exports = (sequelize) => {
// Define User.
return User;
}

Resources