Sequelize not creating set/get/add methods - javascript

I'm not sure if I am missing something, but the Sequelize seems not to create the methods derived from belongsToMany(...) Association (in this case: setRequest, getRequest, addRequest Sequelize Docs)
I'm trying to create a N:N relationship (With Foods and Requests). So, a request can have many foods, and a food can have many requests
The error I get:
(node:4504) UnhandledPromiseRejectionWarning: TypeError: food.addRequests is not a function
Models
Request Model:
const { Model, DataTypes } = require('sequelize');
class Request extends Model {
static init(sequelize) {
super.init({
//Format
client: DataTypes.STRING(70),
time_processing: DataTypes.INTEGER,
time_cooking: DataTypes.INTEGER,
time_paying: DataTypes.INTEGER,
//Has one Table
}, {
//Conection
sequelize
})
}
static associate(models) {
this.belongsTo(models.Table, { foreignKey: 'fk_table', as: 'table', targetKey: 'id' });
this.belongsTo(models.Employee, { foreignKey: 'fk_employee', as: '' });
this.belongsToMany(models.Food, { foreignKey: 'fk_request', through: 'requests_foods', as: 'request' });
}
}
module.exports = Request;
Food Model:
const { Model, DataTypes } = require('sequelize');
class Food extends Model {
static init(sequelize) {
super.init({
//Format
name: DataTypes.STRING(40),
image: DataTypes.STRING,
price: DataTypes.FLOAT,
storage: DataTypes.INTEGER,
//Is used By Many Requests
}, {
//Conection
sequelize,
tableName: 'foods'
})
}
static associate(models) {
//Through: Table used to join data
//foreignKey: Which column of requests_foods is used to reference to models.Request
this.belongsToMany(models.Request, { foreignKey: 'fk_food', through: 'requests_foods', as: 'foods' });
this.belongsTo(models.Category, { foreignKey: 'fk_category', as: 'category' });
}
}
module.exports = Food;
The pivot table:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('requests_foods', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
fk_request: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: 'requests', key: 'id' },
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
},
fk_food: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: 'foods', key: 'id' },
onUpdate: 'CASCADE',
onDelete: 'RESTRICT'
},
amount: {
type: Sequelize.INTEGER,
allowNull: false,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
},
updated_at: {
type: Sequelize.DATE,
allowNull: false,
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('requests_foods');
}
};
And Finally, the Controller (Where the error is thrown)
const Request = require('../models/Request');
const Food = require('../models/Food');
module.exports = {
async list(req, res) {
const dbResponse = await Request.findAll();
return res.json(dbResponse);
},
async add(req, res) {
const { client, time_processing, time_cooking, time_paying, fk_table, fk_employee, foods } = req.body;
console.log(req.body);
const dbResponse = await Request.create({ client, time_processing, time_cooking, time_paying, fk_table, fk_employee });
//Look for food list
foods.map(async item => {
console.log('ITEM:', item);
const food = await Food.findByPk(item.fk_food)
console.log(food);
food.addRequests(); //ERROR HERE
})
return res.json(dbResponse);
}
}
Notes:
The request is added, but the requests_foods not.
I tried changing to: addRequest(), setRequests, setRequest(), but nothing works, I console.log the object, and it seems that the object just doesn't have any method:
{ client: 'Wesley Almeida Braga',
time_processing: 0,
time_cooking: 0,
time_paying: 0,
fk_table: 1,
fk_employee: 1,
foods: [ { fk_food: 1 } ] }
Executing (default): INSERT INTO `requests` (`id`,`client`,`time_processing`,`time_cooking`,`time_paying`,`created_at`,`updated_at`,`fk_employee`,`fk_table`) VALUES (DEFAULT,?,?,?,?,?,?,?,?);
ITEM: { fk_food: 1 }
Executing (default): SELECT `id`, `name`, `image`, `price`, `storage`, `created_at` AS `createdAt`, `updated_at` AS `updatedAt`, `fk_category` FROM `foods` AS `Food` WHERE `Food`.`id` = 1;
Food {
dataValues:
{ id: 1,
name: 'Carne de Sol',
image: 'example_2.png',
price: 25,
storage: 10,
createdAt: 2020-01-12T03:48:34.000Z,
updatedAt: 2020-01-12T03:48:34.000Z,
fk_category: 1 },
_previousDataValues:
{ id: 1,
name: 'Carne de Sol',
image: 'example_2.png',
price: 25,
storage: 10,
createdAt: 2020-01-12T03:48:34.000Z,
updatedAt: 2020-01-12T03:48:34.000Z,
fk_category: 1 },
_changed: {},
_modelOptions:
{ timestamps: true,
validate: {},
freezeTableName: false,
underscored: true,
paranoid: false,
rejectOnEmpty: false,
whereCollection: { id: 1 },
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'Food', singular: 'Food' },
omitNull: false,
sequelize:
Sequelize {
options: [Object],
config: [Object],
dialect: [MysqlDialect],
queryInterface: [QueryInterface],
models: [Object],
modelManager: [ModelManager],
connectionManager: [ConnectionManager],
importCache: {} },
tableName: 'foods',
hooks: {} },
_options:
{ isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes:
[ 'id',
'name',
'image',
'price',
'storage',
'createdAt',
'updatedAt',
'fk_category' ] },
isNewRecord: false }

Related

How to find several fields of a foreign key in a join table in Node.js Sequelize

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

Empty Array when use random with Sequelize

I'm working on an API in Node.js with the Sequelize ORM.
I make an API route to retrieve a random question, it works one time out of three but often returns an empty array. I can't find a solution in the documentation to prevent this...
app.get('/:certifName/:levelName/random', async function (req, res) {
return await Certification.findOne(
{
attributes: ['id', 'label'],
include: [{
model: CertificationLevel,
as: "tcl",
required: true,
attributes: ['id', 'label', 'question_number', 'exam_duration'],
include: [{
attributes: ['id', 'label'],
model: CertificationChapter,
as: "tcc",
required: true,
limit: 1,
order: [ [ Sequelize.fn('RANDOM') ] ],
include: [{
model: Question,
as: "tq",
required: true,
include: [{
model: QuestionChoice,
as: "tqc",
required: false,
attributes: ['id', 'label_fr', 'is_answer'],
}],
}],
}],
where: { label: req.params.levelName }
}],
where: { label: req.params.certifName }
})
.then(data => {
if (data) {
res.send(data);
}
else
res.sendStatus(204);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Error retrieving certification details"
});
});
});
The last model :
module.exports =
class CertificationLevel extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
label: Sequelize.STRING,
slug: Sequelize.STRING,
description: Sequelize.TEXT,
question_number: Sequelize.INTEGER,
exam_duration: Sequelize.INTEGER,
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW
},
updated_at: Sequelize.DATE,
deleted_at: Sequelize.DATE
},
{
tableName: 't_certifications_levels',
sequelize,
underscored: true,
timestamps: false
},
);
}
static associate(models) {
this.belongsTo(models.Certification, {
onDelete: "CASCADE",
foreignKey: {
allowNull: false,
name: "certification_id"
}
}),
this.hasMany(models.CertificationChapter, { as:'tcc', foreignKey: 'level_id' })
this.hasMany(models.Subscription, { as:'ts',foreignKey: 'level_id' })
}
}
And this is a SQL query generate :
SELECT "Certification".*,
"tcl"."id" AS "tcl.id",
"tcl"."label" AS "tcl.label",
"tcl"."question_number" AS "tcl.question_number",
"tcl"."exam_duration" AS "tcl.exam_duration"
FROM
(SELECT "Certification"."id",
"Certification"."label"
FROM "t_certifications" AS "Certification"
WHERE "Certification"."label" = 'ISTQB'
AND
(SELECT "tcl"."certification_id"
FROM "t_certifications_levels" AS "tcl"
WHERE ("tcl"."label" = 'Fondation'
AND "tcl"."certification_id" = "Certification"."id")
LIMIT 1) IS NOT NULL
LIMIT 1) AS "Certification"
INNER JOIN "t_certifications_levels" AS "tcl" ON "Certification"."id" = "tcl"."certification_id"
AND "tcl"."label" = 'Fondation';
I don't know why I have two executing to my route?
I am a real beginner in back development...
Thank for you help

Sequelize polymorphic many to many - `add` mixin not working

I have a many-to-many polymorphic association setup for customer surveys. The issue that I have run into is when using the add mixin on the model instance of Survey. If the joining table already has an item with the surveyed field equal to the id of the new surveyable, it gets overwritten.
survey table:
id
name
1
'Customer Survey'
scheduled_sessions table:
id
appointment_data
10
{ "someData" : [] }
service_provider table:
id
name
10
Joe Doe
survey_surveyable table:
survey
surveyable
surveyed
1
serviceProvider
10
When I add a scheduled session that happens to have the same id as a service provider, the join table row is overwritten:
const surveyInstance = await DB.Survey.findByPk(1);
const scheduledSessionInstance = await DB.ScheduledSession.findByPk(10);
surveyInstance.addScheduledSession(
scheduledSessionInstance,
{ through: { surveyable: "scheduledSession" } }
);
return surveyInstance.save();
This is the SQL queries that sequelize runs:
SELECT "id", "name"
FROM "surveys" AS "Survey"
WHERE "Survey"."id" = 1;
SELECT "id", "appointment_data" AS "appointmentData"
FROM "scheduled_sessions" AS "ScheduledSession"
WHERE "ScheduledSession"."id" = 10;
SELECT "survey", "surveyable", "surveyed"
FROM "survey_surveyable" AS "SurveySurveyable"
WHERE
"SurveySurveyable"."survey" = 1 AND
"SurveySurveyable"."surveyed" IN (10);
UPDATE "survey_surveyable"
SET "surveyable"=$1
WHERE
"survey" = $2 AND
"surveyed" = $3
Since both the scheduled session and the service provider have id=10, the service provider row in the join table is overwritten resulting in:
survey_surveyable table:
survey
surveyable
surveyed
1
scheduledSession
10
where it should have been:
survey_surveyable table:
survey
surveyable
surveyed
1
serviceProvider
10
1
scheduledSession
10
Is this a sequelize issue, or am I using the add mixin incorrectly?
My models:
Survey.js:
module.exports = (sequelize, DataTypes) => {
class Survey extends sequelize.Sequelize.Model {};
Survey.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false
}
},
{
timestamps: false,
tableName: "surveys",
sequelize
}
);
Survey.associate = (models) => {
Survey.belongsToMany(models.ScheduledSession, {
through: {
model: models.SurveySurveyable,
unique: false
},
foreignKey: "survey",
constraints: false
});
};
return Survey;
};
ScheduledSession.js:
module.exports = (sequelize, DataTypes) => {
class ScheduledSession extends sequelize.Sequelize.Model {};
ScheduledSession.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
}
appointmentData: {
type: DataTypes.JSONB,
allowNull: false,
field: "appointment_data"
}
},
{
paranoid: true,
tableName: "scheduled_sessions",
sequelize
}
);
ScheduledSession.associate = (models) => {
ScheduledSession.belongsToMany(models.Survey, {
through: {
model: models.SurveySurveyable,
unique: false,
scope: {
surveyable: "scheduledSession"
}
},
foreignKey: "surveyed",
constraints: false
});
};
return ScheduledSession;
};
ServiceProvider.js:
module.exports = (sequelize, DataTypes) => {
class ServiceProvider extends sequelize.Sequelize.Model {};
ServiceProvider.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
}
name: {
type: DataTypes.STRING,
allowNull: false
}
},
{
paranoid: true,
tableName: "service_provider",
sequelize
}
);
ServiceProvider.associate = (models) => {
ServiceProvider.belongsToMany(models.Survey, {
through: {
model: models.SurveySurveyable,
unique: false,
scope: {
surveyable: "serviceProvider"
}
},
foreignKey: "surveyed",
constraints: false
});
};
return ServiceProvider;
SurveySurveyable.js:
module.exports = (sequelize, DataTypes) => {
class SurveySurveyable extends sequelize.Sequelize.Model {};
SurveySurveyable.init(
{
survey: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
surveyable: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true
},
surveyed: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
constraints: false
}
},
{
timestamps: false,
tableName: "survey_surveyable",
sequelize,
freezeTableName: true
}
);
return SurveySurveyable;
};
You are using Survey's mixin but missing scope in Survey's association.
Survey.associate = (models) => {
Survey.belongsToMany(models.ScheduledSession, {
through: {
model: models.SurveySurveyable,
unique: false,
scope: { // This is missing
surveyable: "scheduledSession"
}
},
foreignKey: "survey",
constraints: false
});
};

How can I parse complex query operations using Sequelize.js?

I have an Option table which has a question_id as a foreign key to table Questions.
Then in Questions table I've 2 foreign keys namely question_category_id and section_id. For the 1st Option part I am able to apply LEFT OUTER JOIN query but also I need to fetch the values of Question_Category and Section table as well.
Let me first clear out how I want my output to be:
Output JSON
"questions": [
{
"id": 9,
"isActive": true,
"question_text": "What is abc ?",
"createdBy": "avis",
"questionCategory": {
"id": 1,
"name": "aptitude"
},
"section": {
"id": 1,
"marks": 5
},
"options": [
{
"id": 1,
"answer": true,
"option_text": "A",
"question_id": 9
},
{
"id": 2,
"answer": false,
"option_text": "B",
"question_id": 9
}
]
}
]
Now I am specifying my database models:
question_category.js
module.exports = (sequelize, Sequelize) => {
const QuestionCategory = sequelize.define('question_category', {
id:{ type: Sequelize.BIGINT, autoIncrement: true, allowNull: false, primaryKey: true },
isActive: { type: Sequelize.BOOLEAN, allowNull: false },
question_category_name: { type: Sequelize.STRING, allowNull: false },
createdBy: { type: Sequelize.STRING, allowNull: false },
createdAt: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }
}, { timestamps: false });
return QuestionCategory;
};
section.js
module.exports = (sequelize, Sequelize) => {
const Section = sequelize.define('section', {
id: { type: Sequelize.BIGINT, autoIncrement: true, allowNull: false, primaryKey: true },
isActive: { type: Sequelize.BOOLEAN, allowNull: false },
marks_per_question: { type: Sequelize.INTEGER, allowNull: false },
createdBy: { type: Sequelize.STRING, allowNull: false },
createdAt: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }
}, { timestamps: false });
return Section;
};
question.js
module.exports = (sequelize, Sequelize) => {
const Questions = sequelize.define('questions', {
id:{ type: Sequelize.BIGINT, autoIncrement: true, allowNull: false, primaryKey: true },
isActive: { type: Sequelize.BOOLEAN, allowNull: false },
question_text: { type: Sequelize.STRING, allowNull: false },
createdBy: { type: Sequelize.STRING, allowNull: false },
createdAt: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }
}, { timestamps: false });
return Questions;
};
option.js
module.exports = (sequelize, Sequelize) => {
const Options = sequelize.define('options', {
id:{ type: Sequelize.BIGINT, autoIncrement: true, allowNull: false, primaryKey: true },
answer: { type: Sequelize.BOOLEAN, allowNull: true },
option_text: { type: Sequelize.STRING, allowNull: false },
createdAt: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }
}, { timestamps: false });
return Options;
};
In the database.js i.e. the main js file for exporting the models I have associated the models like this:
const dbConfig = require('../config/db.config');
const Sequelize = require('sequelize');
const sequelize = new Sequelize(
dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD,
{
host: dbConfig.HOST,
port: dbConfig.PORT,
dialect: 'mysql',
operatorsAliases: 0
}
);
sequelize.authenticate().then(() => {
console.log('Connection has been established successfully.');
}).catch(err => {
console.error('Unable to connect to the database:', err);
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.QuestionCategory = require('./question_model/question_category')(sequelize, Sequelize);
db.Section = require('./question_model/section')(sequelize, Sequelize);
db.Question = require('./question_model/question')(sequelize, Sequelize);
db.Option = require('./question_model/option')(sequelize, Sequelize);
// Relating Question Category with Questions
db.QuestionCategory.hasMany(db.Question, {
foreignKey: 'question_category_id',
sourceKey: 'id'
});
db.Question.belongsTo(db.QuestionCategory, {
foreignKey: 'question_category_id',
targetKey: 'id'
});
// Relating Sections with Questions
db.Section.hasMany(db.Question, {
foreignKey: 'section_id',
sourceKey: 'id'
});
db.Question.belongsTo(db.Section, {
foreignKey: 'section_id',
targetKey: 'id'
});
// Relating Questions with Options
db.Question.hasMany(db.Option, {
foreignKey: 'question_id',
sourceKey: 'id'
});
db.Option.belongsTo(db.Question, {
foreignKey: 'question_id',
targetKey: 'id'
});
So this is my structure.
Now to achieve the above output format I've written the below logic but it's not outputting the correct JSON:
const db = require('../models/database');
const errors = require('../config/errors').errors;
exports.viewQuestion = (req, res, next) => {
try {
db.Question.findAll({
attributes: { exclude: ['createdAt','section_id','question_category_id'] },
include: [{
model: db.Option,
attributes: { exclude: ['createdAt'] }
}]
}).then(data => {
if(data.length == 0) {
return res.status(200).send({
status: 200,
questions: 'No Data'
});
}
db.QuestionCategory.findAll({
attributes: { exclude: ['createdBy','createdAt','isActive'] },
include: db.Question,
attributes: { exclude: ['id','isActive','question_text','createdBy','createdAt','section_id'] }
}).then(question_category => {
Object.assign(data[0], { 'questionCategories': question_category });
res.status(200).send({
status: 200,
questions: data
});
});
}).catch(err => {
return res.status(204).send(errors.MANDATORY_FIELDS);
});
} catch(err) {
return res.status(204).send(errors.MANDATORY_FIELDS);
}
};
I didn't wrote the logic for Section part yet as I was going Step by Step. The output that I am getting by writing this logic is:
{
"status": 200,
"questions": [
{
"id": 9,
"isActive": true,
"question_text": "What is abc ?",
"createdBy": "avis",
"options": [
{
"id": 1,
"answer": true,
"option_text": "A",
"question_id": 9
},
{
"id": 2,
"answer": false,
"option_text": "B",
"question_id": 9
}
]
}
]
}
The questionCategories didn't got reflected in the output.
Please help me out as I've more scenarios like this and all I can solve depending on this.
If you are using Sequelize to get objects from a DB via models then you should turn them into plain objects before adding some properties. For instance, if you get a collection of objects you should call get({ plain: true }) for each of them.
const plainObj = data[0].get({ plain: true })
Object.assign(plainObj, { 'questionCategories': question_category });
res.status(200).send({
status: 200,
questions: plainObj
});

fliped foreign key relations?

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.

Categories

Resources