Associations in sequelize - javascript

I've read through all the documentation and googled it a ton and I still can't figure this out. I'm trying to setup a database that allows users to be able to create an event/activity and assign multiple tags to it (indoors, food, breakfast) to categorize the events. I'm using postgres and sequelize. I'm also unsure of how I would query these events. Would I use app.get?
Currently I have an activities table and a tags table and a 3rd join table.
Tags table:
'use strict';
module.exports = (sequelize, DataTypes) => {
var Tag = sequelize.define('Tag', {
title: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
Tag.hasMany(models.Activity, { through: models.ActivityTag, foreignKey: 'tag_id' });
}
}
});
return Tag;
};
Activities table:
'use strict';
module.exports = (sequelize, DataTypes) => {
var Activity = sequelize.define('Activity', {
description: DataTypes.STRING,
location: DataTypes.STRING,
title: DataTypes.STRING,
cost: DataTypes.INTEGER
}, {
classMethods: {
associate: function(models) {
console.log(models);
Activity.belongsToMany(models.Tag, {as: 'activity' through: models.ActivityTag, foreignKey: 'activity_id' });
}
}
});
return Activity;
};
Join table:
'use strict';
module.exports = (sequelize, DataTypes) => {
var ActivityTag = sequelize.define('ActivityTag', {
activity_id: DataTypes.INTEGER,
tag_id: DataTypes.INTEGER
}, {
classMethods: {
associate: function(models) {
}
}
});
return ActivityTag;
};

Related

Node.js, Sequelize, cannot convert undefined or null to object

I'm working on an API and have a special problem. When a make a GET request, i received my JSON Data but the server crash with an error :
for (const key of Object.keys(this.constructor._attributeManipulation)) {
TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
at Timeout._onTimeout (/Users/quentin/O'Clock/motogpapi/node_modules/sequelize/lib/model.js:83:34)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
I can't undersant origin of this crash. you can find below the code. Is it possible this problem due to as wrong data into db ?
Model team.js:
const { DataTypes, Model } = require("sequelize");
const sequelize = require("../database/client");
class Teams extends Model {}
Teams.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
constructorId: {
type: DataTypes.INTEGER,
allowNull: false
},
isOfficial: {
type: DataTypes.BOOLEAN,
allowNull: false
},
championshipId: {
type: DataTypes.INTEGER,
allowNull: false
},
}, {
sequelize,
tableName: "team"
});
module.exports = Teams;
Model Constructor.js
const { DataTypes, Model } = require("sequelize");
const sequelize = require("../database/client");
class Constructors extends Model {}
Constructors.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
model: {
type: DataTypes.STRING,
allowNull: false
},
engine: {
type: DataTypes.STRING,
allowNull: false
},
}, {
sequelize,
tableName: "constructor"
});
module.exports = Constructors;
Model Index.js i used for associations
const Teams = require("./teams");
const Championships = require("./championships");
const Constructors = require("./constructors");
Constructors.hasMany(Teams, {
foreignKey: "constructorId",
as: "teamsList"
});
Teams.belongsTo(Constructors, {
foreignKey: "constructorId",
as: "constructor"
});
Championships.hasMany(Teams, {
foreignKey: "championshipId",
as: "teamsList"
});
Teams.belongsTo(Championships, {
foreignKey: "championshipId",
as: "championship"
});
module.exports = {
Teams,
Championships,
Constructors
};
The Controller :
const { Teams } = require("../models");
const teamsController = {
async getAllTeams(_, response) {
try {
const teamsList = await Teams.findAll({
include: ["constructor", "championship"]
});
response.json(teamsList);
} catch (error) {
console.log(error);
}
}
};
module.exports = teamsController;
And database/client.js
require("dotenv").config();
const { Sequelize } = require("sequelize");
const sequelize = new Sequelize(process.env.PG_URL, {
define: {
underscored: true
}
});
(async () => {
try {
await sequelize.authenticate();
console.log("Connection has been established successfully.");
} catch (error) {
console.error("Unable to connect to the database:", error);
}
})();
module.exports = sequelize;

Node.js - SequelizeDatabaseError: column "user_id" does not exist

I have a very simple schema but when I try to make a call for a data it returns me the error
SequelizeDatabaseError: column "user_id" does not exist
My database consists of three tables only. Below is the schema file for all of them:
Users
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('users', {
email: DataTypes.STRING,
password: DataTypes.STRING
}, {});
User.associate = function (models) {
User.hasMany(models.survey_instances)
};
return User;
};
Survey instances
module.exports = (sequelize, DataTypes) => {
const SurveyInstances = sequelize.define('survey_instances', {
userId: {
field: 'user_id',
type: DataTypes.INTEGER
},
templateId: {
field: 'template_id',
type: DataTypes.INTEGER
},
fields: DataTypes.JSONB,
}, {
underscored: true,
});
SurveyInstances.associate = function (models) {
SurveyInstances.belongsTo(models.survey_templates, { foreignKey: 'templateId' })
SurveyInstances.belongsTo(models.users, { foreignKey: 'userId' })
};
return SurveyInstances;
};
Survey Templates
module.exports = (sequelize, DataTypes) => {
const SurveyTemplates = sequelize.define('survey_templates', {
fields: DataTypes.JSONB,
}, {});
SurveyTemplates.associate = function (models) {
SurveyTemplates.hasMany(models.survey_instances)
};
return SurveyTemplates;
};
My database is populated and I make the call by:
http://localhost:3000/templates?id=1
The code handling this endpoint in node is:
app.get('/templates', authenticateToken, async (req, res) => {
const templates = await db.survey_instances.findByPk(1);
res.send(templates);
});
I'm new to node so maybe the error is obvious but I cant see it. I would really appreciate it if someone helped me out. Thank you!
I figured out the issue. There is a bug in the new Sequelize updates that don't make the underscored: true option work. More details can be found here.
So I am now just using camel case instead of snake case. Everthing's working now.

Sequelize error using association on n:m related objects

I am using nodeJS, express (4.17.1), sequelize (5.21.4) and mysql (mysql2 v2.1.0) for a current project.
In my database I have three tables Filter, Element and FilterElement. If I query data from database from Filter or Element table separatly I get the result of objects with data. If I want to use "connecting" table FilterElement I get this error {"name":"SequelizeEagerLoadingError"}
EagerLoadingError [SequelizeEagerLoadingError]: filter_element is not
associated to filters_new!
What is wrong with my code?
These are my sequelize objects codes.
Filter.js
const Sequelize = require('sequelize');
const db = require('../config/database');
const Filter = db.define('filters_new', {
Model:{
type: Sequelize.STRING,
primaryKey: true,
allowNull: false
}
},
{
timestamps: false,
freezeTableName: true
}
);
Filter.associate = function(models) {
Filter.belongsToMany(models.Element, {
through: models.FilterElement,
as: 'filter',
foreignKey: 'FilterHousingModel'
});
};
module.exports = Filter;
Element.js
const Sequelize = require('sequelize');
const db = require('../config/database');
const Element = db.define('filter_element', {
idfilter_element:{
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false
},
ElementName:{
type: Sequelize.STRING,
}
},
{
timestamps: false,
freezeTableName: true
}
);
Element.associate = function(models) {
Element.belongsToMany(models.Filter, {
through: models.FilterElement,
as: 'element',
foreignKey: 'FilterElementId'
});
};
module.exports = Element;
FilterElemnt.js
const Sequelize = require('sequelize');
const db = require('../config/database');
const FilterElement = db.define('filters_new', {
idfilter_filterelement:{
type: Sequelize.STRING,
primaryKey: true,
allowNull: false,
autoincrement: true
},
FilterHousingModel: {
type: Sequelize.STRING
},
FilterElementId: {
type: Sequelize.INTEGER
}
},
{
timestamps: false,
freezeTableName: true
}
);
module.exports = FilterElement;
If I call this function, I do get the desired result of data from database.
listFiltersOnly(req, res) {
return filter.findAll()
.then((filters) => {
res.status(200).send(filters);
})
.catch(err => {
console.log(err);
res.status(400).send(err);
});
}
then if I call function list I get the error mentioned up EagerLoadingError
list(req, res) {
return filter.findAll({
include: [{
model: element,
as: 'element'
}],
})
.then((filters) => {
console.log(filters);
res.status(200).send(filters);
})
.catch(err => {
console.log(err);
res.status(400).send(err);
});
}
Looking for some suggjestions where might be the problem?
#RatulSharker I removed the asociation from the model and added it where the models are implemented in the controller and now I do get some results.
Filter.belongsToMany(FilterElement, {
through: FilterFilterElement,
foreignKey: 'FilterHousingModel'
});
FilterElement.belongsToMany(Filter, {
through: FilterFilterElement,
foreignKey: 'FilterElementId'
});
Thank you #Ratul Sharker

NodeJS Sequalize Table1 is not associated to Table2

I have two tables table1 and table2. i want to get relational data. I gone through this URL which is same as the my error but that solution is not work for me
module.exports = function (sequelize, DataTypes) {
var table1 = sequelize.define("table1", {
table1Id: {type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true},
image: {type: DataTypes.STRING},
}, {
timestamps: true,
classMethods: {
associate: function (models) {
table1.belongsTo(models.table2, {
onDelete: "CASCADE",
foreignKey: {
name: "table2Id",
notEmpty: false
}
});
}
}
});
return table1;
};
and another is :
module.exports = function (sequelize, DataTypes) {
var table2 = sequelize.define("table2", {
table2Id: {type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true},
name: {type: DataTypes.STRING},
}, {
timestamps: true,
classMethods: {
associate: function (models) {
table2.hasMany(models.table1, {
onDelete: "CASCADE",
foreignKey: {
name: "table1Id",
notEmpty: false
}
});
}
}
});
return table2;
};
then in controllers:
models.table2.findById(req.params.id, {
include: [{model: models.table1}]
}).then(function (data) {
}).catch(Sequelize.ValidationError, function (err) {
return res.status(422).send(err.errors);
}).catch(function (err) {
console.log(err.message,"err.message")
return res.status(400).send({
message: err.message
});
});
and i got error that Table1 is not associated to Table2
If you are on sequelize >4
The way association are defined is changed.
Instead of defining association as
const Model = sequelize.define('Model',
{ ... },
{ classMethods: { associate: function (model) {...} }
});
They are now defined as
const Model = sequelize.define('Model', { ... });
// Class Method
Model.associate = function (models) { ...associate the models };
This could also justify why it seems to work on one machine and not the other.

Sequelize v3 — how do I make the default value for a hasMany relationship an empty list?

I am using Sequelize as my ORM. I have a simple User model as follows. A User hasMany comments, and a Comment belongsTo a user.
models/user.js (trimmed to what's relevant)
const model = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING
}
},
{
classMethods: {
associate: function(models) {
User.hasMany(models.Comment, {as: 'comments'})
}
}
}
)
return User
}
module.exports = model
models/comment.js (also trimmed)
const model = (sequelize, DataTypes) => {
const Comment = sequelize.define('Comment', {
text: {
type: DataTypes.TEXT
}
}, {
classMethods: {
associate: function(models) {
Comment.belongsTo(models.User, {as: 'author'})
}
}
}
)
return Comment
}
module.exports = model
I've created a test as follows (trimmed for brevity)
describe('create user given simple valid data', () => {
const userData = {
name: 'test'
}
it('creates a user', (done) => {
User.create(userData, {
include: [{model: models.Comment, as: 'comments'}]
}).then((user) => {
const userJS = user.get({plain: true})
expect(userJS).to.have.property('name')
expect(userJS).to.have.property('comments')
done()
}, done)
})
})
which results in
Unhandled rejection AssertionError: expected { Object (name, ...) } to have a property 'comments'
If I specify my userData like this however
const userData = {
name: 'test',
comments: []
}
the test passes just fine.
How can I tell Sequelize to just make an empty list of comments as the default?
Actually, this feature is not part of the models creation.
It relates to the Query when getting data.
You can use the nested:true option in include statement of findAll.
User.findAll({
include: [{
model: Comment,
as: "comments",
nested: true
}]});
source: http://docs.sequelizejs.com/manual/models-usage.html#nested-eager-loading

Categories