My idea is to have the ability to add multiple strings at keyword, I've been told to use foreign keys and so am I. But I can't figure out why it's not working properly. Any ideas?
My code is as follows
user.js
var User = sequelize.define('user', {
username: Sequelize.STRING,
myhash: Sequelize.TEXT,
mysalt: Sequelize.STRING,
keyword: Sequelize.STRING
});
var keywordData = sequelize.define('keywordData', {
keywords: Sequelize.STRING
})
User.hasMany(keywordData)
keywordData.belongsTo(User)
User.js
router.post("/newkeyword", function(req, res) {
keywordData.update(
{keywordData: req.body.newkeyword},
{where: {id: req.user['id']}}
)
})
You forgot to indicate a foreignKey option in the second association definition as well as create an auto-increment id for keywordData model.
var keywordData = sequelize.define('keywordData', {
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, },
keywords: { Sequelize.STRING }
})
Hence, your association should be like this:
User.hasMany(keywordData)
keywordData.belongsTo(User, {foreignKey: 'keyword', targetKey: 'keywords' })
Also you an refer this document for more details.
Related
I'm trying to define some specific M:N association using sequelize v6.20.1 and i'm facing and issue...
I have 2 models, an Account model and a Group model.
My rules about these models are the following:
An account can exists without any group
An account can have multiple groups
A group can exists with a least one account associated, so that mean a group cannot exists without an account associated
A group can be associated with multiple accounts
Here is the code definition of all models and association :
const Sequelize, { Model, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: `./database.sqlite`,
});
/* ----- Account model ----- */
class Account extends Model {
// Some account's methods definitions...
}
Account.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: DataTypes.STRING,
username: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
}, { sequelize });
/* ----- Group model ----- */
class Group extends Model {
// Some group's methods definitions...
}
Group.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: DataTypes.STRING,
}, { sequelize });
/* ----- AccountGroup model ----- */
class AccountGroup extends Model {
}
AccountGroup.init({
AccountId: {
type: DataTypes.INTEGER,
references: {
model: Account,
key: 'id',
},
onDelete: 'RESTRICT',
},
GroupId: {
type: DataTypes.INTEGER,
references: {
model: Group,
key: 'id',
},
allowNull: false,
onDelete: 'CASCADE',
},
}, {
sequelize,
timestamps: false,
});
/* ----- Association definition ----- */
Account.belongsToMany(Group, { through: AccountGroup });
Group.belongsToMany(Account, { through: AccountGroup });
sequelize.authenticate();
sequelize.sync({ force: true };
(async () => {
const group = new Group({ name: 'Group' });
await group.save();
const account = new Account({ name: 'Doe', username: 'John', email: 'john.doe#example.com', password: 'secret' });
account.addGroup(group);
await account.save();
// some processing code...
await account.destroy();
})();
After account.destroy() finished, the AccountGroup row is successfully deleted but not the Group. And i want to delete unreferenced groups.
What am i missing ?
This is the way that the cascading deletes works. In your example, when the Account is deleted, rows in the AccountGroup table may now have an invalid value in their AccountId foreign key column. You are telling the database that when this situation occurs, delete the AccountGroup entirely. Similarly, if you delete a Group, this will cascade down and delete any AccountGroup with that Group as its GroupId.
No such issue arises for the Account or Group tables when an AccountGroup is deleted. They do not contain any foreign keys that have been made invalid.
To find the functionality that you are searching for, deleting any groups that no longer belong to an AccountGroup, you will likely want to put a separate query in your code, or you may be able to use a Hook to be executed after an Account is deleted.
I have 2 models Prophet and Task and they have a m:n relationship:
Prophets
const prophet = sequelize.define('prophets', {
name: {
type: Sequelize.STRING,
primaryKey: true,
unique: true
}
});
prophet.relationship = function(task) {
prophet.belongsToMany(task, {
through: 'prophetTasks',
as: 'tasks',
foreignKey: 'prophetName'
});
};
Tasks
const task = sequelize.define('tasks', {
name: {
type: Sequelize.STRING,
primaryKey: true,
unique: true
}
});
task.relationship = function(prophet) {
task.belongsToMany(prophet, {
through: 'prophetTasks',
as: 'prophets',
foreignKey: 'taskName'
});
};
EDITED:
my problem is sometimes I have to update a prophet which might remove some relationships with tasks, but I cant figure out how to delete the tasks that have no more relationship with any prophets.
I believe I should find all tasks that doesnt belong in prophetTasks table anymore, but I dont know how to query that with sequelize
You can use ON DELETE CASCADE
So whenever the row is deleted, data containing it as a foreign key will be deleted.
I have the following two tables in Sequelize
const Tokens = sequelize.define("Tokens", {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
active: {
type: DataTypes.BOOLEAN
}
});
and
const User = sequelize.define("Users", {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
first_name: {
type: DataTypes.STRING
}
});
User.associate = models => {
models["Users"].hasMany(models["Tokens"], {foreignKey: 'userID', as: 'tokens_userid'});
};
I'm trying to run the following query in Sequelize.
const token = await db.Tokens.findOne({
where: {
id,
active: true
},
include: ["tokens_userid"]
});
But I'm getting the following error.
Error: Association with alias "tokens_userid" does not exists
My main goal is to get the user based on a Token ID. Now I would just move that association to the User table, but the problem with that later on I will want to get all the tokens for a given User ID. So I will run into this problem either way.
I tried adding the following line, but it was complaining about circular relations or something like that.
models["Tokens"].hasOne(models["User"], {foreignKey: 'userID', as: 'tokens_userid'});
How can I query either the Users or Tokens table and have it populate correctly with the relation?
I was able to solve this by adding the following line to my table.
models["Tokens"].belongsTo(models["User"], {foreignKey: 'userID', as: 'tokens_userid_from_token'});
Basically what I tried before but changed hasOne to belongsTo.
Hopefully this helps someone else.
I have a question in sequelize orm.
There is Many to Many relationship between tables , through a middle table.
const Tag = sequelize.define('tag', {
name: Sequelize.STRING,
type: Sequelize.CHAR
})
const Image = sequelize.define('image', {
thumb: Sequelize.STRING,
original: Sequelize.STRING,
status: Sequelize.INTEGER,
width: Sequelize.INTEGER,
height: Sequelize.INTEGER,
fileSize: Sequelize.STRING,
})
const TagImages = sequelize.define('TagImages', {
value: Sequelize.STRING,
})
When I find an image by Id , I get all tags well by include, But I cannot get the value column in tagImages table.
This is my query statement:
Image.findById(imageId,{ include: [Tag] })
.then(image => {
console.log(image);
})
and there is no column of value in my console.log. How should I get it?
Sequelize should put a TagImage property on each included Tag.
I’m trying to delete tasks when delete a associated farmer. I have read a sequelize docs and i have done the same solutions in there. But i can not delete tasks automatically. Also I have tried solutions in the following links:
Sequelize onDelete not working
Sequelize.js onDelete: 'cascade' is not deleting records sequelize
I'm using sequelizejs with mysql.
My models:
Task.js
'use strict';
var Farmer = require('./farmer');
module.exports = function(sequelize, DataTypes) {
var Task = sequelize.define('Task', {
title: DataTypes.STRING,
deadline: DataTypes.DATE,
description: DataTypes.TEXT,
FarmerId: {
type: DataTypes.INTEGER,
references: {
// This is a reference to another model
model: Farmer,
// This is the column name of the referenced model
key: 'id'
}
}
}, {
classMethods: {
associate: function(models) {
Task.belongsTo(models.Farmer, {foreignKey: 'FarmerId'});
// associations can be defined here
}
}
});
return Task;
};
Farmer.js
'use strict';
var validator = require('validator');
module.exports = function(sequelize, DataTypes) {
var Farmer = sequelize.define('Farmer', {
username:{
type: DataTypes.STRING,
allowNull: false,
},
address: DataTypes.STRING,
email: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
validate: {
isEmail: { args: true, msg: "not a valid email!" },
len: { args: [0, 100], msg: "email can't be bigger than 100"},
}
},
phone:{
type: DataTypes.STRING,
allowNull: false,
},
}, {
classMethods: {
associate: function(models) {
Farmer.hasMany(models.Task, {onDelete: 'CASCADE', hooks:true});
// associations can be defined here
}
}
});
return Farmer;
};
What else can I do?
Also, Do I need to set ‘on delete cascade’ on mysql related table? If I don’t do it, sequelize define association onDelete doesnt work?
You can omit FarmerId in your definition of Task. Sequelize automatically knows that there's a FarmerId by associating Task with Farmer. Try that, everything else seems very usual.