Sails js and Sequelize, no associations added to database - postgresql

This is how my models are structured in sails:
myapp
--api
----controllers
----models
-----User.js
------Role.js
User.js
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
}
},
associations: function() {
User.hasOne(Role, {foreignKey: 'id', as: 'role' });
}
};
Role.js
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
}
}
};
After sails lift, in the postgresql I have users table with id, username, password, createdat and updatedat + roles table with id, name, createdat and updatedat. No foreignKey for Roles in Users table.
How I can fix this?
I'm using sails-hook-sequelize and sails-hook-sequelize-blueprints, can this occur because of them?
Thanks!
Edit:
The correct way was:
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
}
},
associations: function() {
User.hasOne(Role, {
as : 'role',
foreignKey: {
name: 'roleId',
allowNull: false
}
});
}
};

The createdAt and updatedAt columns are added by default unless you set the timestamps option to false. See the docs.
To add foreign key constraints, you need to define associations for the Roles model.

Related

hasMany foreignKey not working in Sequelize

I have some models - kanban_cards, kanban_checklists, kanban_checkitems.
kanban_cards model:
export default (sequelize, DataTypes) => {
return sequelize.define('kanban_card', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false
},
label: {
type: DataTypes.STRING,
allowNull: true,
},
listId: {
type: DataTypes.UUID,
allowNull: false
},
...
})
}
kanban_checklist:
export default (sequelize, DataTypes) => {
return sequelize.define('kanban_checklist', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false
},
cardId: {
type: DataTypes.UUID,
allowNull: false,
}
})
}
And the association is:
const models = {
KanbanCards: KanbanCards(sequelize, Sequelize.DataTypes),
KanbanChecklists: KanbanChecklists(sequelize, Sequelize.DataTypes),
...
}
...
models.KanbanCards.hasMany(models.KanbanChecklists, { as: 'checklists', foreignKey: 'cardId' })
models.KanbanChecklists.belongsTo(models.KanbanCards)
It works fine if I use findAll, but if I try to create, it doesn't work.
It says.
column "kanbanCardId" of relation "kanban_checklists" does not exist
I am going to use cardId rather than kanbanCardId.
I tried to set references to cardId, but it didn't work either.
If you indicated an explicit foreign key column in hasMany you should do the same for the other part - belongsTo:
models.KanbanChecklists.belongsTo(models.KanbanCards, { foreignKey: 'cardId' })
Otherwise Sequelize generate a foreign key name itself like in your case kanbanCard+id:
The name of the foreign key in the join table (representing the target model) or an object representing the type definition for the other column (see Sequelize.define for syntax). When using an object, you can add a name property to set the name of the column. Defaults to the name of target + primary key of target

Property won't insert properly in Sequelize Model Create

I want to insert username, password, and role. But when I executed my function, the role property won't be executed.
This is my migration file:
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
type: Sequelize.STRING,
unique: true,
},
password: {
type: Sequelize.STRING,
allowNull: false,
},
role: {
type: Sequelize.STRING,
allowNull: false,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
And this is my function for inserting new data (usermodel.js)
static register = ({ username, password }) => {
const encryptedPassword = this.encrypt(password);
return this.create({ username, password: encryptedPassword, role: 'user' })
}
This is what I got when I executed the function:
Executing (default): INSERT INTO "UserModel" ("id","username","password","createdAt","updatedAt") VALUES (DEFAULT,$1,$2,$3,$4) RETURNING "id","username","password","createdAt","updatedAt";
Is there anything that I do wrong? Any help will be appreciated, thanks!
Apparently, the problem is within the model. I haven't defined the role in the model init. I solved it by adding the role in model:
UserModel.init({
username: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING
}

Sequelize delete instance with n:m and 1:m associations and update Model

I have 2 models in my postgresql db and using sequelize and node:
Users
Transactions
and are associated like this:
UserModel.hasMany(TransactionModel, { as: 'sentTransactions', foreignKey: 'senderId' });
UserModel.hasMany(TransactionModel, { as: 'receivedTransactions', foreignKey: 'receiverId' });
UserModel.belongsToMany(TransactionModel, { as: 'transactionLikes', through: 'UserLike', foreignKey: 'userId' });
TransactionModel.belongsTo(UserModel, { as: 'receiver' });
TransactionModel.belongsTo(UserModel, { as: 'sender' });
TransactionModel.belongsToMany(UserModel, { as: 'likers', through: 'UserLike', foreignKey: 'transactionId' });
Which means a user has many received and sent transactions and each user can "like" many transactions.
How can I delete a transaction and remove all associations (receiver, sender, liker)? I don't want to delete the users too.
I would also like to update the User Model which is defined like this, in order to add an "email" property:
const UserModel = db.define('user', {
id: { type: Sequelize.STRING, unique: true, primaryKey: true },
firstName: { type: Sequelize.STRING },
lastName: { type: Sequelize.STRING },
username: {
type: Sequelize.STRING,
unique: {
args: true,
msg: USERNAME_IS_TAKEN,
},
}
How can I update the model? What will happen to the existing instances?
Thank you in advance for your help!
According to this tutorial your M:N relation should work as you expect it out of the box:
For n:m, the default for both is CASCADE. This means, that if you delete or update a row from one side of an n:m association, all the rows in the join table referencing that row will also be deleted or updated.
Further more, to enforce the CASCADE behavior you may also pass onDelete option to the association calls. Something like this should do the trick:
TransactionModel.belongsToMany(UserModel, { as: 'likers', through: 'UserLike', foreignKey: 'transactionId', onDelete: 'CASCADE' });
Adding an email property to the User Model should be as easy as that:
const UserModel = db.define('user', {
id: {
type: Sequelize.STRING,
unique: true,
primaryKey: true
},
firstName: { type: Sequelize.STRING },
lastName: { type: Sequelize.STRING },
username: {
type: Sequelize.STRING,
unique: {
args: true,
msg: USERNAME_IS_TAKEN,
}
},
email: { type: Sequelize.STRING }
});

How to set up PostgreSQL database with associations between tables (foreign keys) with Sequelize

I'm using PostgreSQL, Sequelize, and Sequelize-cli.
Using sequelize-cli and some manipulation in an IDE I set up the following model and migration file (simplified for the example, I didn't include the "Users" migration file):
Model File
// models/annotation.js
module.exports = function (sequelize, DataTypes) {
var Annotation = sequelize.define('Annotation', {
userId: {
type: DataTypes.INTEGER,
references: {model: "User", key: 'id'},
},
url: DataTypes.STRING,
source: DataTypes.STRING,
body: DataTypes.TEXT,
exact: DataTypes.TEXT,
}, {
classMethods: {
associate: function (models) {
// associations can be defined here
Annotation.belongsTo(models.User, {foreignKey: "userId"});
},
},
});
return Annotation;
};
Corresponding migration file
// migrations/20161121050521-create-annotation.js
const User = require("../models/user");
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('Annotations', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER,
references: {model: User, key: 'id'},
allowNull: false
},
...
Referenced Model
// models/user.js
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('User', {
title: DataTypes.STRING,
name: DataTypes.STRING,
email: DataTypes.STRING,
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
User.hasMany(models.Annotation, {foreignKey: "userId"});
}
}
});
return User;
};
I'm running the follow cli commands:
"dropdb -U postgres annotate && curl -XDELETE 'http://localhost:9200/_all'"
"createdb -U postgres annotate"
"node_modules/.bin/sequelize db:migrate"
When I migrate I get the following error:
SequelizeDatabaseError: relation "User" does not exist
From the documentation I was under the impression that Annotation.belongsTo(models.User would have been enough to establish the association, but when I did that my db tables didn't have any foreign key fields.
How can I establish tables with associations to one another?

Getting "model is not associated with other Model" in sequelize when using belongsToMany

I am using sequelize with postgreSQL. I have two schemas namely User and Location. A User can have many Locations and a Location can have many Users.
My User Schema is as follows
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: Sequelize.STRING,
require: true
},
middleName: {
type: Sequelize.STRING,
require: false
},
lastName: {
type: Sequelize.STRING,
require: true
},
age: {
type: Sequelize.INTEGER,
require: false
},
email_Id: {
type: Sequelize.STRING,
require: true,
unique: true,
validate: {
isEmail: true
}
}
My Location Schema is as follows:
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
latitude: {
type: Sequelize.DOUBLE,
require: true
},
longitude: {
type: Sequelize.DOUBLE,
require: true
},
locationAddress: {
type: Sequelize.STRING
},
mailBoxNo: {
type: Sequelize.INTEGER
}
I Am using belongsToMany of sequelize and creating a third table name UserLocation where I have mentioned belongsToMany for both User and Location which is as below:
User.belongsToMany(Location, {
through: 'UserLocation'
});
Location.belongsToMany(User, {
through: 'UserLocation'
});
My requirement is to get all the locations for a given user id. My Code is as follows:
var param = req.body;
var options = {};
if (param.where) {
options.where = param.where;
}
options.include = [{
model: User //User Model
}, {
model: Location //Location Model
}];
//Here userLocation refers to UserLocation Schema
userLocation.findAll(options).then(function (response) {
//Some Logic
}).catch(function (err) {
//Error handling
});
While executing the above code, I getting the following error:
User Model is not associated with UserLocation Model.
I am unable to understand why I am getting the following error. Can somebody help me out with this?
You can use this for getting all the locations of a given user;
User
.findOne({
"where": {
"id": param.where
},
"include": [Location]
})
.then(function(user) {
// should get this user
console.log(user);
// should get all locations of this user
console.log(user.Locations);
})
.catch(function(error) {
// error handling
});