i dont understand what should i do when i have erorr "model is not defined" when i GET the data from the postman. i'm a newbie for node.js and javascript
my dir is:
app
--models
----user.js
model
--users.js
routes
--users.js
i've the app/models/user.js is:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class users 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
}
};
users.init({
name: DataTypes.STRING,
email: DataTypes.STRING,
phone_number: DataTypes.STRING,
gender: DataTypes.BOOLEAN
}, {
sequelize,
modelName: 'users',
});
return users;
};
i've model/users.js is :
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER(5)
},
name: {
type: Sequelize.STRING(30)
},
email: {
type: Sequelize.STRING(50)
},
phone_number: {
type: Sequelize.STRING(15)
},
gender: {
type: Sequelize.BOOLEAN,
defaultValue: true
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('NOW'),
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('NOW'),
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('users');
}
};
and i've routes/users.js is :
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', async function (req, res, next) {
try {
const users = await model.users.findAll({});
if (users.length !== 0) {
res.json({
'status': 'OK',
'messages': '',
'data': users
})
} else {
res.json({
'status': 'ERROR',
'messages': 'EMPTY',
'data': {}
})
}
} catch (err) {
res.json({
'status': 'ERROR',
'messages': err.message,
'data': {}
})
}
});
module.exports = router;
i run the node server in the postman with GET, and my result is:
{
"status": "ERROR",
"messages": "model is not defined",
"data": {}
}
You have not import the model file in this file "routes/users.js
var model = require("./app/models/user.js");
Related
I have a Node.js application with Express, Sequelize as ORM and PostgreSQL for the database. In this app I have candidate model and mission model as below.
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class candidat extends Model {
static associate(models) {
this.belongsToMany(models.mission, {
through: "candidat_mission",
foreignKey: "candidatId",
otherKey: "idMission",
});
}
}
candidat.init({
candidatId: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
firstName: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
isEmail: true,
allowNull: false,
type: DataTypes.STRING,
unique: true,
},
}, {
sequelize,
modelName: 'candidat',
tableName: 'candidat',
freezeTableName: true,
});
return candidat;
};
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class mission extends Model {
static associate(models) {
this.belongsToMany(models.candidat, {
through: "candidat_mission",
foreignKey: "idMission",
otherKey: "candidatId",
})
}
}
mission.init({
idMission: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
title: {
type: DataTypes.STRING,
allowNull: false
},
aliasTitle: {
type: DataTypes.STRING,
allowNull: true
},
description: {
type: DataTypes.TEXT,
allowNull: true
}
}, {
sequelize,
modelName: 'mission',
tableName: 'mission',
freezeTableName: true,
});
return mission;
};
These two models are linked in many-to-many by a candidate_mission join table. In this model, I added fields like a foreign key which points to another table, that of users.
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class candidat_mission extends Model {
static associate(models) {
this.belongsTo(models.user, { foreignKey: "fk_user" });
}
}
candidat_mission.init({
candidatMissionId: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
candidatId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: { tableName: 'candidat' },
key: "candidatId",
},
},
idMission: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: { tableName: 'mission' },
key: "idMission",
},
},
fk_user: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: { tableName: 'user' },
key: "userId",
},
},
}, {
sequelize,
modelName: 'candidat_mission',
tableName: 'candidat_mission',
timestamps: true,
freezeTableName: true,
});
return candidat_mission;
};
When I make a "GET" request, I do have the information from the candidate_mission table (if a candidate is linked to this mission), but for the user it only returns the ID and I would like it to return all the fields present in the Users model, what can I do?
Here, my function in the mission controller which allows to add a candidate to this mission :
const addCandidats = async (req, res) => {
try {
const mission = await Mission.findByPk(req.body.idMission);
if (mission) {
const candidat = await Candidat.findByPk(req.body.candidatId);
if (candidat) {
mission.addCandidat(candidat,
{through: {
fk_user: req.body.fk_user && req.body.fk_user
}});
return res.status(200).send(mission);
} else {
console.log("Candidat non trouvé");
return null;
}
} else {
console.log("Mission non trouvée!")
return null;
}
} catch (error) {
console.log(error);
}
};
Currently, my query returns me this :
"candidat_mission":
{
"candidatMissionId": 2,
"candidatId": 1,
"idMission": 7,
"fk_user": 1,
"createdAt": "2023-02-14T10:34:08.302Z",
"updatedAt": "2023-02-14T15:06:10.232Z"
},
And i want it to come back to me :
"candidat_mission":
{
"candidatMissionId": 2,
"candidatId": 1,
"idMission": 7,
"fk_user": {
"userId": 1,
"email": "blabla#gmail.com",
"name": "blabla"
},
"createdAt": "2023-02-14T10:34:08.302Z",
"updatedAt": "2023-02-14T15:06:10.232Z"
},
After associating 2 models, we have to query again to get the object along with the relationship.
await mission.addCandidat(candidat,
{through: {
fk_user: req.body.fk_user && req.body.fk_user
}});
const result = await CandidatMission.findOne({
where: { candidatId: req.body.candidatId, idMission: req.body.idMission },
include: models.user,
})
return res.status(200).send(result);
I'm trying to order a findByPk result that includes an association (Many to many) in Sequelize, but I'm having some issues. I keep getting the error:
Error: Unable to find a valid association for model, 'Item'
The query:
Guest.findByPk(id,
{
include: { model: db.Item, as: 'items' },
order: [
[ { model: db.sequelize.models.Item, as: 'items' }, 'dexId', 'ASC' ]
]
})
.then(data => {
res.status(200).json({ items: data.items});
})
.catch(err => {
const error = new createError(500, "Error retrieving Guest with id=" + id);
return next(error);
});
Item model:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Item 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) {
Item.belongsToMany(models.Guest, {
//through: 'GuestItems',
through: {
model: 'GuestItems',
unique: false
},
constraints: false,
as: 'guests',
foreignKey: 'itemId',
otherKey: 'guestId'
});
Item.belongsToMany(models.User, {
//through: 'UserItems',
through: {
model: 'UserItems',
unique: false
},
constraints: false,
as: 'users',
foreignKey: 'itemId',
otherKey: 'userId'
});
}
}
Item.init({
dexId: {
allowNull: true,
type: DataTypes.INTEGER,
defaultValue: null
},
name: {
type: DataTypes.STRING,
unique: true,
allowNull: false
},
description: DataTypes.STRING,
filename: DataTypes.STRING,
}, {
sequelize,
modelName: 'Item',
paranoid: true
});
return Item;
};
Guest model
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Guest 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) {
Guest.belongsToMany(models.Item, {
through: 'GuestItems',
as: 'items',
foreignKey: 'guestId',
otherKey: 'itemId'
});
}
}
Guest.init({
id: {
type: DataTypes.BIGINT,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
token: DataTypes.STRING,
role: {
type: DataTypes.ENUM,
values: ["guest"],
defaultValue: "guest"
},
lastIPAddress: DataTypes.STRING
}, {
sequelize,
modelName: 'Guest',
associations: true
});
return Guest;
};
I know for a fact db.sequelize.models.Item exists, I've also tried calling db.Item (Which again, exists and is used elsewhere) - and neither work.
I've also tried
[ db.sequelize.models.Item, 'dexId', 'ASC' ]
instead of the { as 'items' } bit, but I still get that error.
I'm using the latest versions of Sequelize and Postgresql
Guest.findByPk(id, {
include: {model: db.Item, as: 'items', required: true},
order: [[sequelize.literal('"items"."dexId"'), 'ASC']]
})
.then((data) => {
res.status(200).json({items: data.items});
})
.catch((err) => {
return next(error);
});
I'm using postgres with sequelize. I'm trying to create a Products table in the database. On the main script file (app.js), i called the sequelize.sync() to synchronise the modal with the database. But, no matter how many times i tried, the table was not made in the database. The only query that was executed is this;
Executing (default): SELECT 1+1 AS result
But, when i import a modal into the app.js file, the syncing occurs fine. I'm really confused by this behaviour.
These are my files;
./utils/database.js
const { Sequelize } = require("sequelize");
module.exports = new Sequelize("mydatabase", "myname", "mypassword", {
host: "localhost",
dialect: "postgres",
operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
},
});
./modals/product.js
const { Sequelize, DataTypes } = require("sequelize");
const sequelize = require("../utils/database.js");
const Product = sequelize.define("Product", {
id: {
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
title: {
type: DataTypes.STRING,
},
price: {
type: DataTypes.DOUBLE,
allowNull: false,
},
imageUrl: {
type: DataTypes.STRING,
},
description: {
type: DataTypes.STRING,
},
});
// export the Modal
module.exports = Product;
./app.js
const sequelize = require("./utils/database.js");
sequelize.sync()
.then(() => {
// listen
app.listen(3000, () => {
console.log("Server running...");
});
})
.catch((error) => {
console.log(error);
});
The above code fails to sync. But if i import the modal into this file, it works fine.
const sequelize = require("./utils/database.js");
// importing Product modal
const Product = require("./models/product.js");
sequelize.sync()
.then(() => {
// listen
app.listen(3000, () => {
console.log("Server running...");
});
})
.catch((error) => {
console.log(error);
});
Is it always needed to import all modals into the app.js file if want to use the sync() function?
Changing your file structure little bit, Try like below
./utils/database.js
const { Sequelize } = require("sequelize");
const sequelize = new Sequelize("mydatabase", "myname", "mypassword", {
host: "localhost",
dialect: "postgres",
operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
},
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
module.exports = db;
./modals/product.js
const { DataTypes } = require("sequelize");
const db = require("../utils/database.js");
const Product = db.sequelize.define("Product", {
id: {
type: DataTypes.UUID,
defaultValue: db.Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
title: {
type: DataTypes.STRING,
},
price: {
type: DataTypes.DOUBLE,
allowNull: false,
},
imageUrl: {
type: DataTypes.STRING,
},
description: {
type: DataTypes.STRING,
},
});
// export the Modal
module.exports = Product;
i have a strange effekt at a m:n relation..
this are the model definitions:
Role Model:
'use strict';
module.exports = (sequelize, DataTypes) => {
const Role = sequelize.define('Role', {
uuid: {
allowNull: false,
primaryKey: true,
unique: true,
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
....
}, {});
/** #param models.User */
Role.associate = function(models) {
Role.belongsToMany(
models.User, {
through: 'user_role',
foreignKey: 'userId',
}
);
};
return Role;
};
User Model:
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
uuid: {
allowNull: false,
primaryKey: true,
unique: true,
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
....
}, {});
/** #param models.Role */
User.associate = function(models) {
User.belongsToMany(
models.Role, {
through: 'user_role',
foreignKey: 'roleId',
}
);
};
return User;
};
the migration is the following:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('user', {
uuid: {
allowNull: false,
unique: true,
primaryKey: true,
type: Sequelize.UUIDV4,
defaultValue: Sequelize.UUIDV4,
},
....
}).then(() => {
queryInterface.createTable('role', {
uuid: {
allowNull: false,
unique: true,
primaryKey: true,
type: Sequelize.UUIDV4,
defaultValue: Sequelize.UUIDV4,
},
....
});
}).then(() => {
queryInterface.createTable('user_role', {
userId: {
type: Sequelize.UUIDV4,
references: {
model: 'User',
key: 'uuid',
},
allowNull: false,
},
roleId: {
type: Sequelize.UUIDV4,
references: {
model: 'Role',
key: 'uuid',
},
allowNull: false,
},
....
});
}).then(() => {
return queryInterface.addConstraint('user_role', ['UserId', 'RoleId'], {
unique: true,
type: 'primary key',
name: 'userrole_pkey',
});
});
},
down: (queryInterface, Sequelize) => {
....
},
};
if i try to insert now a user with a new role:
let models = require('../models');
models.Role.create({
role: 'Administrator',
description: 'Administrator Gruppe',
}).then(role => {
models.User.create({
login: 'admin',
password: '123',
nick: 'Admini',
mail: 'admin#localhost.com',
}).then(user => {
user.addRole(role);
user.save().then(() => {
console.log('admin created');
}).catch(err => {
console.log(err);
});
}).catch(err => {
console.log(err);
});
}).catch(err => {
console.log(err);
});
it tries to add the role uuid in the userid and the user uuid in the roleid.. and for that the constraint fails...
any hints or tips where i made a mistake?
found the mistake myself (with help of a college)
at
models.User, {
through: 'user_role',
foreignKey: 'userId',
}
i set the wrong foreign key, it's not the field in the helper table, it's needed to be the source table (in this case uuid of user model) or leave it blank for sequelize's default behaviour to use the primary key.
I have 2 models: User and Foto
Each User has a lot of fotos, and each foto can have just 1 user related.
To do that i use include, the problem is, i can use the include just when i am querying the user and not when i query the foto.
I get there is no relationshop between User and foto problem.
So at the moment i have this:
Model User:
"use strict";
var sequelize = require('./index');
var bcrypt = require('bcrypt-nodejs');
var Foto = require('./Foto');
module.exports = function (sequelize, DataTypes) {
var User = sequelize.define("User", {
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isUnique: function (value, next) {
var self = this;
User.find({ where: { username: value } })
.then(function (user) {
// reject if a different user wants to use the same username
if (user && self.id !== user.id) {
return next('username already in use!');
}
return next();
})
.catch(function (err) {
return next(err);
});
}
}
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isUnique: function (value, next) {
var self = this;
User.find({ where: { email: value } })
.then(function (user) {
// reject if a different user wants to use the same email
if (user && self.id !== user.id) {
return next('Email already in use!');
}
return next();
})
.catch(function (err) {
return next(err);
});
}
}
},
typeOfUser: {
type: DataTypes.INTEGER,
allowNull:false,
defaultValue:2
},
country: {
type: DataTypes.STRING,
allowNull:true,
defaultValue:null
},
birthDate:{
type: DataTypes.DATEONLY,
allowNull:true,
defaultValue:null
},
reports: {
type: DataTypes.INTEGER,
defaultValue: 0
},
points: {
type: DataTypes.INTEGER,
defaultValue: 0
},
password: {
type: DataTypes.STRING,
allowNull:false
},
numberFotos: {
type: DataTypes.INTEGER,
defaultValue: 0
}
}, {
classMethods: {
generateHash: function (password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
},
associate: function(models){
User.hasMany(models.Foto,{foreignKey: "userId", as: "Fotos"});
}
},
instanceMethods: {
validPassword: function (password) {
return bcrypt.compareSync(password, this.password);
}
}
});
return User;
}
Model Foto:
"use strict";
var sequelize = require('./index');
var bcrypt = require('bcrypt-nodejs');
var User = require('./User');
module.exports = function (sequelize, DataTypes) {
var Foto = sequelize.define("Foto", {
reports: {
type: DataTypes.INTEGER,
defaultValue: 0
},
image: {
type: DataTypes.STRING,
allowNull: false
},
date: {
type: DataTypes.DATE,
allowNull: true
},
lat: {
type: DataTypes.STRING,
allowNull: true
},
lon: {
type: DataTypes.STRING,
allowNull: true
},
altitude: {
type: DataTypes.STRING,
allowNull: true
},
userId: {
type: DataTypes.INTEGER,
allowNull: false
},
plantId: {
type: DataTypes.INTEGER,
allowNull: true
},
},
{
associate: function (models) {
Foto.belongsToMany(models.User, {as:'Users'});
}
}
);
return Foto;
}
then i try to get something like this in a json three:
[{
FotoA:{
prop1:value1,
prop2:value2,
user:{
userProp1
}
}
FotoB:{
}
}]
on my route i do the following:
allPictures: function (req, res) {
Foto.findAll({include: [{ model: User, as: "Users",where:{userId: User.id} }]})
.then(function (fotos) {
res.send(fotos);
})
},
if there is a better way to do this instad of eager loading please share it, i just need to get the userId and the username.
Thanks
I guess you defined the association wrong, as you mentioned a Foto should belong to one User.
try
Foto.belongsTo(model.User);
instead of
associate: function (models) {
Foto.belongsToMany(models.User, {as:'Users'});
}
And also there should be no need for the where clause when selecting. If your associations are defined correctly, you can simply do
Foto.findAll({include: [models.User]})