How to insert all values from another table using sequelize - javascript

//table main_lookup
const main_lookup=DB.connection.define('main_lookup',{
main_lookup_name: {
type :Sequelize.STRING,
primaryKey: true,
allowNull: false
},
value:{
type:Sequelize.JSON,
allowNull:false,
}
});
//table 2
const school_lookup= DB.connection.define('school_lookup',{
school_id : {
type :Sequelize.STRING,
allowNull: false,
references: {
model: schools,
key: 'school_id'
}
},
lookup_name: {
type :Sequelize.STRING,
unique: true,
allowNull: false
},
value: {
type: Sequelize.JSON,
allowNull: false,
}
});
i need to send data from main_lookup table to school lookup data
school_id // that is given by me
lookup_name // that is copy from main_lookup
value // that is copy from main_look_up
example
main lookup // table1
main_lookup_name value
---------------- -----
language ['english','tamil']
subject ['social','maths']
the solution is similar to the content following this
school_lookup // table2 //needed
school_id lookup value
--------- ------ -----
cit language ['english','tamil']
cit subject ['social','maths']
i need help in sequelize with simple ways

You can use raw query to do the same.
var Sequelize = require('sequelize');
var sequelize = new Sequelize('database', 'username', 'password');
sequelize.query("insert into <table1> select * from <table2>", {
type:Sequelize.QueryTypes.SELECT
}).then(function(results) {
console.log(results) // or do whatever you want
})

I think you are using sequelize like how people use microsoft excel or microsoft access. You can simply make relation in sequelize.
here is the code
//school-model
const School=Sequelize.define('school',{
name: {
type :Sequelize.STRING,
allowNull: false
}
});
//subject
const Subject= Sequelize.define('subject',{
type: {
type :Sequelize.STRING,
unique: true,
allowNull: false
},
value: {
type: Sequelize.ARRAY,
allowNull: false,
}
});
//database
const School = require('./path_to_schoolmodel');
const Subject = require('./path_to_subjectmodel');
Subject.belongsTo(School);
School.hasMany(Subject);
School model
id name
-- ---------------------
1 'fullstack academy'
2 'app academy'
Subject model
id type value schoolID
-- --------- -------------------- ------------------
1 language ['english','tamil'] 2
2 subject ['social','maths'] 1
if you setup model relationship you should be able to see you data like this.
Then when you use Sequelize model querying on your server side.
const School = require('./path_to_schoolmodel');
const Subject = require('./path_to_subjectmodel');
School.findAll({
include:[ Subject ]
})
.then(console.log)
.catch(console.error)
your console.log should return something like
[
{
id: 1,
name: 'fullstack academy'
subjects: [{
id: 2,
type: 'subject',
value: [
'socials', 'maths'
]
}]
},
{
id: 2,
name: 'app academy'
subjects: [{
id: 1,
type: 'language',
value: [
'english', 'tamil'
]
}]
},
]

Related

Sequelize: Create multiple self association

I have model "Subject" which has self relationship with it self "Successor" and "Predecessor". For that i required to create two foreign key "successorId" and "predecessorId".
I am able to create relation but don't how to add entry in foreign key.
Model Subject:
const { sequelize } = require('../config/databaseInit');
const { DataTypes, Model } = require('sequelize');
class Subject extends Model {}
Subject.init(
{
subjectCode: {
type: DataTypes.STRING(40),
unique: true,
},
subjectName: {
type: DataTypes.STRING(60),
allowNull: false,
},
...
...
...
successorId: {
type: DataTypes.INTEGER,
references: {
model: 'Subject',
key: 'id',
},
},
predecessorId: {
type: DataTypes.INTEGER,
references: {
model: 'Subject',
key: 'id',
},
},
},
{
sequelize: sequelize,
modelName: 'Subject',
tableName: 'Subject',
timestamps: true,
}
);
For example:
const sub1 = await Subject.create({....});
const sub2 = await Subject.create({....});
// None of them are working.
sub1.setSuccessorId(sub2);
sub1.setSuccessor(sub2);
sub1.update({ successorId: sub1.id });
you can identify your relation model 1-n/n-n/1-n
here link: https://sequelize.org/master/manual/assocs.html
example:
Subject.belongsTo(models.Class, { as: 'subject', foreignKey: 'subjectId' });

How to create with association in Sequelize

I have two Sequelize models that are associated with a belongsTo relationship. I would like to create an instance of user_sources when user is created but I am struggling to accomplish it.
model_user:
const User = sequelize.define('user', {
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
password: {
type: Sequelize.STRING,
allowNull: false
}
}, {
tableName: 'users'
})
model_user_sources:
const UserSources = sequelize.define('user_sources', {
abcNews: {
type: Sequelize.BOOLEAN,
},
bbcNews: {
type: Sequelize.BOOLEAN,
}
}, {
tableName: 'user_sources'
})
UserSources.belongsTo(User)
Both models are initialized and the tables are created in the database properly. According to the Sequelize documentation I should be able to create both with association in a single query like so:
User
.create({
email: user.email,
password: user.password,
}, {
include: UserSources
})
However, only the user is created. The user_sources item does not get created in the table.
Unfortunately the documentation only shows an example of creating a parent model from a child model but not the other way around. I have tried several different methods such as using a hasOne association, adding model/association options into the include, putting data into the create method, etc. But I feel as though I am not grasping the concept properly.
Would appreciate if someone could shed some light on my problem. Thanks.
"sequelize": "^5.21.3". Here are three ways to create data records for User and UserSources model with associations. Besides, we keep adding the foreign key constraint using userId to user_sources table.
E.g.
index.js:
import { sequelize } from '../../db';
import Sequelize from 'sequelize';
const User = sequelize.define(
'user',
{
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
password: {
type: Sequelize.STRING,
allowNull: false,
},
},
{
tableName: 'users',
},
);
const UserSources = sequelize.define(
'user_source',
{
abcNews: {
type: Sequelize.BOOLEAN,
},
bbcNews: {
type: Sequelize.BOOLEAN,
},
},
{
tableName: 'user_sources',
},
);
UserSources.belongsTo(User);
// User.UserSources = User.hasOne(UserSources);
// User.hasOne(UserSources);
(async function test() {
try {
await sequelize.sync({ force: true });
// 1. User.UserSources = User.hasOne(UserSources);
// await User.create(
// {
// email: 'example#gmail.com',
// password: '123',
// user_source: {
// abcNews: true,
// bbcNews: true,
// },
// },
// {
// include: [
// {
// association: User.UserSources,
// },
// ],
// },
// );
// 2. User.hasOne(UserSources);
// await User.create(
// {
// email: 'example#gmail.com',
// password: '123',
// user_source: {
// abcNews: true,
// bbcNews: true,
// },
// },
// {
// include: [UserSources],
// },
// );
// 3. UserSources.belongsTo(User);
await UserSources.create(
{
abcNews: true,
bbcNews: true,
user: {
email: 'example#gmail.com',
password: '123',
},
},
{
include: [User],
},
);
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
After executing the above code, check the data records in the database:
node-sequelize-examples=# select * from "users";
id | email | password
----+-------------------+----------
1 | example#gmail.com | 123
(1 row)
node-sequelize-examples=# select * from "user_sources";
id | abcNews | bbcNews | userId
----+---------+---------+--------
1 | t | t | 1
(1 row)
The data records are created as expected.

Sequelize - avoid deleting rows of many-to-many association when inserting a new one

My problem is that when I execute this code:
const task = await db.tasks.findByPk(1)
const user = await db.users.findByPk(4)
await user.setTasks(task)
This happens:
Executing (default): SELECT `tasks`.`id`, `tasks`.`start_date` FROM `tasks` AS `tasks` WHERE `tasks`.`id` = '1';
Executing (default): SELECT `id`, `name`, `surname`, `email`, `role` FROM `users` AS `users` WHERE `users`.`id` = '4';
Executing (default): SELECT `id`, `task_id`, `user_id` FROM `users_tasks` AS `users_tasks` WHERE `users_tasks`.`user_id` = 4;
Executing (default): DELETE FROM `users_tasks` WHERE `user_id` = 4 AND `task_id` IN (2)
Executing (default): INSERT INTO `users_tasks` (`id`,`task_id`,`user_id`) VALUES (NULL,1,4);
The user with id 4 had a previous association with a task with id 2. The issue is, I want to keep that association! It is perfectly fine for the purpose of my application for a user to be assigned to more tasks (and vice versa).
I would actually say that that's the normal desired behaviour of a many-to-many relationship... why is Sequelize deleting the row on users_tasks before adding a new one, and how can I prevent this from happening?
Here is my user model:
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('users', {
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false
},
surname: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(256),
allowNull: false
},
}, {
tableName: 'users',
timestamps: false,
})
User.associate = function (models) {
User.belongsToMany(models.tasks, {through: 'users_tasks', foreignKey: 'user_id'})
}
return User
}
Here is my task model:
module.exports = function(sequelize, DataTypes) {
var Task = sequelize.define('tasks', {
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
start_date: {
type: DataTypes.DATE,
allowNull: true,
},
}, {
tableName: 'tasks',
timestamps: false
})
Task.associate = function (models) {
Task.belongsToMany(models.users, {through: 'users_tasks', foreignKey: 'task_id'})
}
return Task
}
And here is my join table:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('users_tasks', {
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
task_id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
references: {
model: 'tasks',
key: 'id'
}
},
user_id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
references: {
model: 'users',
key: 'id'
}
}
}, {
tableName: 'users_tasks',
timestamps: false
})
}
Do I need to change something on the models definitions, or do I need to change something in the way I call setTasks? Or else, what do I need to do? Why is Sequelize enforcing this weird and unwanted behaviour of deleting previously existing associations?
I found out that I should be using add instead of set if I want to keep the preexisting relations.
So, the correct way of achieving the result I want is this:
const task = await db.tasks.findByPk(1)
const user = await db.users.findByPk(4)
await user.addTasks(task)

Sequelize many-to-many association - Method not found

I have two n:m sequelize models as shown below
// Organization Model
module.exports = {
attributes: {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
required: true
},
},
associations: function() {
Organization.belongsToMany(Contact, {
through : OrganizationContact,
foreignKey: {
name: 'organizationId',
allowNull: false
}
});
}
};
// OrganizationContact Model
module.exports = {
attributes: {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
}
}
}
// Contact Model
module.exports = {
attributes: {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
firstname: {
type: Sequelize.STRING,
required: true
},
lastname: {
type: Sequelize.STRING,
required: false
},
},
associations: function() {
Contact.belongsToMany(Organization, {
through : OrganizationContact,
foreignKey: {
name: 'contactId',
allowNull: false
}
});
}
};
I am trying to insert a contact and attach it to an existing organization. My data looks like
{
"firstname" : "Mathew",
"lastname" : "Brown",
"organizationId" : 1 // Add the contact to an existing organization. I am missing something here.
}
Note : There can be multiple contacts attached to multiple organizations. An organization is created before a contact.
Based on this documentation, after saving the contact when I tried
Organization.addContact(contact);
I get an exception saying
Organization.addContact is not a function
The addContact method should be called on instance of Organization rather than on the model itself, just as you do in the example code.
Organization.create(organizationData).then(organization => {
organization.addContact(contact).then(() => {
// contact was added to previously created organization
});
});
You do not need the organizationId attribute in your contact create data. If you want to add new contact to the organization with id: 1, then you first need to return the organization instance and then perform the addContact method
Organization.findByPrimary(1).then(organization => {
organization.addContact(contact).then(() => {
// contact was added to organization with id = 1
});
});

Sequelize include an attribute from junction table

I'm building a shop, where in the database i have orders and items. Here's the code for the models:
Item:
var Sequelize = require('sequelize')
var sequelize = require('./sequelize')
var Item = sequelize.define('item', {
image: {
type: Sequelize.STRING,
allowNull: false
},
itemName: {
type: Sequelize.STRING,
allowNull: false,
field: 'item_name'
},
price: {
type: Sequelize.INTEGER,
allowNull: false
}
})
module.exports = Item
Order:
var Sequelize = require('sequelize')
var sequelize = require('./sequelize')
var Order = sequelize.define('order', {
orderNumber: {
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4
},
shop: {
type: Sequelize.INTEGER
},
location: {
type: Sequelize.STRING
}
})
module.exports = Order
They are related through belongs to many:
Item.belongsToMany(Order, {through: OrderItem})
Order.belongsToMany(Item, {through: OrderItem})
The OrderItem has an additional field, 'count', which i need to return:
var Sequelize = require('sequelize')
var sequelize = require('./sequelize')
var OrderItem = sequelize.define('OrderItem', {
count: Sequelize.INTEGER
})
module.exports = OrderItem
However, when i try to include the OrderItem model, it doesn't work. No errors, nothing. The query just doesn't return:
Order.findAll({
where: {
userId: userId
},
include: [{
model: Item,
include: [OrderItem]
}]
}).then(orders => {
console.log(orders)
res.status(200).json(orders)
})
How to get what i need from sequeilize?
You may try something like this:
Order.findAll({
where: {
userId: userId
},
include: [{ model: Item,
as:'item',
through:{attributes:['count']} // this may not be needed
}]
}).then(orders => {
console.log(orders)
res.status(200).json(orders)
})
Also, your models must have a right naming strategy. E.g. :
Item - must have itemId field instead of itemNumber,
Order - must have orderId as primary field
OrderItem's structure:
var OrderItem = sequelize.define('OrderItem', {
orderId: Sequelize.INTEGER,
itemId: Sequelize.INTEGER,
count: Sequelize.INTEGER
})
Another one is to use direct names of related fields and models when you use belongsToMany()
More here: http://docs.sequelizejs.com/en/latest/docs/associations/
Turns out that the OrderItem is already nested inside the Item object. However, this doesn't make a nice return format , so the question is still open.
I know this is year later, but yet..
You can use the property joinTableAttributes to get a junction table fields .
for example :
Order.findAll({
where: {
userId: userId
},
joinTableAttributes: ['count'],
include: [{
model: Item,
}]
}).then(orders => {
console.log(orders)
res.status(200).json(orders)
})
I am using Graphql and I had the same problem with the formatting. I did a small map after getting the result.
For example:
let orders = await Order.findAll({
where: {
userId: userId
},
include: [{ model: Item,
as:'item',
through:{attributes:['count']}
}]
});
let ordersWithCount = orders.map((o) => {
let orderWithCount = {};
orderWithCount = o;
orderWithCount.count = o.OrderItem.count;
return orderWithCount;
});

Categories