I'm building a Node/Express app with Sequelize. I created some models and made some database migrations with sequelize-cli with minimal difficulty and decided to add some associations between my entities by adding them to the model files and calling sequelize.sync(). Everything seemed to go smoothly until I made a query to test the associations and I got this error: Association with alias "sender" does not exist on GlobalMessage. Below is the related code:
models/globalmessage.js:
'use strict';
module.exports = (sequelize, DataTypes) => {
const GlobalMessage = sequelize.define('GlobalMessage', {
body: DataTypes.TEXT,
timestamp: DataTypes.DATE,
SenderId: {
type: DataTypes.INTEGER,
references: {
model: "Users",
key: "id"
}
}
}, {});
GlobalMessage.associate = function(models) {
// associations can be defined here
GlobalMessage.belongsTo(models.User, {foreignKey: 'SenderId', as: 'sender'});
};
return GlobalMessage;
};
models/user.js:
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: DataTypes.STRING,
password: DataTypes.STRING,
username: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
User.hasMany(models.GlobalMessage, {
as: 'globalMessages'
})
};
return User;
};
routes/api/user.js:
const Sequelize = require("sequelize");
const express = require("express");
const bcrypt = require('bcrypt');
const saltRounds = 10;
const router = express.Router();
const db = require("../../db/index");
const UserModel = require("../../models/user");
const User = UserModel(db, Sequelize);
const GlobalMessageModel = require("../../models/globalmessage")
const GlobalMessage = GlobalMessageModel(db, Sequelize);
router.post("/findOne", function (request, response, next) {
GlobalMessage.findOne({
where: {body: 'Body of message 1'}, include: 'senders'
})
.then((foundUser) => {
response.json(foundUser)
})
.catch((err) => {
console.log("Error while finding user: ", err)
})
})
module.exports = router;
I get the error when I send a request to localhost/api/user/findOne. I've searched all over and have found little documentation about this specific error and any advice I've found hasn't proven to be fruitful to me. Any help would be appreciated!
Related
const express = require("express");
const router = express.Router();
const bcrypt = require("bcrypt");
const { Users } = require("../../models/Users");
router.post("/", async (req, res) => {
const { username, password } = req.body;
bcrypt.hash(password, 10).then((hash) => {
Users.create({
username: username,
password: hash,
});
res.json("SUCCESS");
});
});
models/Users.js
module.exports = (sequelize, DataTypes) => {
const Users = sequelize.define("Users", {
username: {
type: DataTypes.STRING,
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
});
return Users;
};
Hello i have problem with creating user in my db. The error is TypeError: Cannot read properties of undefined (reading 'create'). I dont know what is wrong. Help me please.
Your models/Users.js module exports a function, not the Users object that you need. Instead of having sequelize and DataTypes as function parameters, you should require them in the module:
const {sequelize, DataTypes} = require("sequelize");
module.exports = {
Users: sequelize.define("Users", {
...
})
};
I am creating realtionship (one to many) between User model and Task model
I have crated the reference column in the migration too
I am using sequlize ORM with sequelize cli. Everything works fine when I try alternative method that i will explain later but If i try to do it according the documentation it gives me error
Task is not associated to User
WORKING ALTERNATIVE METHOD
IN end of index.js file I created relations and it works as expected
db.user = require("../models/user.js")(sequelize, Sequelize);
db.tasks = require("../models/Task.js")(sequelize, Sequelize);
db.user.hasMany(db.tasks, { as: "user_tasks",foreignKey: "userId" });
db.tasks.belongsTo(db.user, {
foreignKey: "userId",
as: "task_user",
});
but when i follow the documetation i got error that i mentioned earlier
According to document
Model User.js
module.exports = (sequelize, DataTypes) => {
const User =sequelize.define('User',{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
age: {
type: DataTypes.INTEGER,
},
email: {
type: DataTypes.STRING,
},
createdAt: {
allowNull: false,
type: DataTypes.DATE
},
updatedAt: {
allowNull: false,
type: DataTypes.DATE
}
});
User.associate = (models) =>{
User.hasMany(models.Tasks, {
as: 'user_tasks',
foreignKey: 'userId'}
);
};
return User;
};
Model: Task.js
module.exports = (sequelize, DataTypes) => {
const Task = sequelize.define('Task', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
userId: {
type: DataTypes.INTEGER,
},
});
Task.associate = function(models) {
Task.belongsTo(models.User, {
as:'owner',
foreignKey:'userId',
onDelete: "cascade"
});
};
return Task;
}
This is how i am trying to get data from database
controller
const User = db.user
const {Tasks} = db.tasks
exports.usertasks = async(req,res)=>{
// const users = await User(db.sequelize,db.Sequelize).findAll({
const users = await User.findAll({
include:[{model:Tasks,as:"user_tasks"}]
});
res.json(users)
console.log("All users with their associated tasks:", JSON.stringify(users, null, 4));
}
My Index.js file
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname+'../models/', file))(sequelize, Sequelize.DataTypes);
console.log(model);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
//relations THIS IS WORKING AND I AM JUST CURIOUS WHETHER TO USE THIS APPROACH OR NOT
// db.user = require("../models/user.js")(sequelize, Sequelize);
// db.tasks = require("../models/Task.js")(sequelize, Sequelize);
// db.user.hasMany(db.tasks, { as: "user_tasks",foreignKey: "userId" });
// db.tasks.belongsTo(db.user, {
// foreignKey: "userId",
// as: "task_user",
// });
module.exports = db;
I am also attaching the picture of successful response that I get with the alternative method.
Kindly, guide whether the alternative method that I used is acceptable or should I stick to the documenation one?
.associate is not a native Model's method, so you need to call it manually.
I think in your index.js you want to do something like:
'use strict';
const Sequelize = require('sequelize');
const config = require('../config/config.json')[process.env.NODE_ENV || 'development'];
const requireAll = require('require-all');
const sequelize = config.use_env_variable
? new Sequelize(process.env[config.use_env_variable], config)
: new Sequelize(config.database, config.username, config.password, config);
const db = { sequelize };
const modelsInitializers = Object.values(requireAll({
dirname: __dirname,
recursive: false,
filter: (name) => name !== 'index.js' && name,
}));
const models = modelsInitializers.map((initializer) => {
const model = initializer(sequelize, Sequelize.DataTypes);
db[model.name] = model;
return model;
});
models.forEach((model) => {
if (model.associate) model.associate(db);
})
models.forEach((model) => {
if (model.associate) model.associate(models);
db[model.name] = model;
})
Object.entries().forEach(([modelName, model]) => {
model.associate(models);
db[modelName] = model;
});
module.exports = db;
Client.js
const mongoose = require("mongoose");
var Schema = mongoose.Schema;
const clientSchema = new mongoose.Schema(
{
name: { type: String, required: true, default: "" },
}, {
timestamps: true
}
);
module.exports = mongoose.model("Client", clientSchema);
User.js
const mongoose = require("mongoose");
var Schema = mongoose.Schema;
const userSchema = new mongoose.Schema({
name: { type: String, required: true, default: "" },
clients: [{
client: {
type: Schema.Types.ObjectId,
ref: "Client",
default: null
},
user_group: {
type: Number
default: null
}
}]
}, { timestamps: true });
module.exports = mongoose.model("User", userSchema);
auth.js (Where trying to populate Clients)
const express = require("express");
const router = express.Router();
const User = require("../models/User");
const Client = require("../models/Client");
router.post("/users", (req, res) => {
let params = req.body;
let total_client = [];
User.findOne({
email: params.email
})
.populate({
path: "clients.client",
model: Client
})
.exec((err, user) => {
console.log(user);
res.send(user);
});
});
module.exports = router;
Please check the above code. I have given code examples of my two models user.js and client.js. In user schema, I have referenced client inside an array object. While querying user, the client is not population. Please help me to get this thing done. Thanks in advance.
The following expects you to provide a name in the json body of your post request (your example uses email which does not exist in the user model). Also, your model is already defining the ref: Client and so you can simplify your request to just include the path clients.client.
router.post("/users", async (req, res) => {
const { name } = req.body;
const user = await User.findOne({ name: name }).populate('clients.client').exec();
res.send(user);
});
Solved this problem just adding an extra parameter in module export of client.js file
module.exports = mongoose.model("Client", clientSchema, "client");
I'm making an app with nodejs and I want to conect to my models but I keep getting the same error:
TypeError: user.findAll is not a function
routes/user.js
const express = require('express');
const router = express.Router();
const db = require('../config/database');
const user = require('../models/users');
router.get('/', (req, res) => user.findAll()
.then(users => {
console.log(users)
res.sendStatus(200);
})
.catch(err => console.log(err)));
module.exports = router;
models/user.js
'use strict';
const Sequelize = require('sequelize');
const db = require('../config/database')
module.exports = (sequelize, DataTypes) => {
const users = sequelize.define('users', {
id: DataTypes.INTEGER,
name: DataTypes.STRING,
age: DataTypes.INTEGER,
email: DataTypes.STRING,
country: DataTypes.STRING,
state: DataTypes.STRING,
city: DataTypes.STRING
}, {});
users.associate = function(models) {
// associations can be defined here
};
return users;
};
you should use db.users.findAll() instead of user.findAll(). it will work
I found out the error, I wasn't importing/exporting properly, I changed my models/user.js file to:
'use strict';
const Sequelize = require('sequelize');
const db = require ('../config/database')
const DataTypes = require('sequelize/lib/data-types')
const User = db.define('users', {
name: DataTypes.STRING,
age: DataTypes.INTEGER,
email: DataTypes.STRING,
country: DataTypes.STRING,
state: DataTypes.STRING,
city: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
};
module.exports = User
I am following the offical Sequelizer docs, but I am unable to get it working with multiple "hasMany" associations.
The below code renders an error:
Unhandled rejection Error: [object Object] is not associated to User!
How is this done correctly?
models/user.js
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
User.hasMany(models.Movie, models.Book)
}
}
});
return User;
};
routes/index.js
var models = require('../models');
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
models.User.findAll({
include: [ models.Task, models.Movie ]
}).then(function(users) {
res.render('index', {
title: 'Sequelize: Express Example',
users: users
});
});
});
module.exports = router;
Found the issue, you have to define them individually (eg User.hasMany twice)
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
User.hasMany(models.Movie),
User.hasMany(models.Books)
}
}
});
return User;
};