I have the following Employee model for a MySQL database:
var bcrypt = require('bcrypt');
module.exports = (sequelize, DataTypes) => {
const Employee = sequelize.define(
"Employee",
{
username: DataTypes.STRING,
password: DataTypes.STRING,
}, {}
);
return Employee;
};
Seeding the database is done by reading a .sql file containing 10,000+ employees via raw queries:
sequelize.query(mySeedingSqlFileHere);
The problem is that the passwords in the SQL file are plain text and I'd like to use bcrypt to hash them before inserting into the database. I've never done bulk inserts before so I was looking into Sequelize docs for adding a hook to the Employee model, like so:
hooks: {
beforeBulkCreate: (employees, options) => {
for (employee in employees) {
if (employee.password) {
employee.password = await bcrypt.hash(employee.password, 10);
}
}
}
}
This isn't working as I'm still getting the plain text values after reseeding - should I be looking into another way? I was looking into sequelize capitalize name before saving in database - instance hook
Your hooks won't be called until you use model's function for DB operation , so if you are running raw query , hooks will never be fired,
Reason : You can write anything inside your raw query , select/insert/update/delete anything , how does sequelize.js know that
it has to fire the hooks. This is only possible when you use methods
like
Model.create();
Model.bulkCreate();
Model.update();
Model.destroy;
And as per DOC raw query doesn't have hooks option to add.
And for MODEL queries you can check that it has option to
enable/disable hook.
Related
i am creating a user, with 'email' field so i want to verify whether that email is already exist or not, if exists error must display. i have my code in express js, node js, angular 6 and mysql database and below is the code to create new user
exports.create = (req, res) => {
// Save to MySQL database
let customer = req.body;
Customer.create(customer).then(result => {
// Send created customer to client
res.json(result);
});
};
where should i use if statement in above code
Thanks in advance
I'm thinking the simplest way of solving your problem is making the email column in the database unique. If you try to insert a new user with an already existing email the query will fail.
Another solution would be that you first do a query that looks in the database if an already existing user has the email (from req.body.email). But that would require having two different SQL queries, which I personally would not prefer.
i think you are using Sequelize ORM.
You can do like this
Customer.findOrCreate({
where: {
email: req.body.email,
},
// other datas needs to inserted
defaults: {
name: req.body.name,
username: req.body.username,
},
}).spread((data, created) => {
if (created) {
// your logics
} else {
res.status(400).send(`${req.body.email} already exists.`);
}
});
I think I've done enough research on this subject and I've only got a headache.
Here is what I have done and understood: I have restructured my MySQL database so that I will keep my user's data in different tables, I am using foreign keys. Until now I only concluded that foreign keys are only used for consistency and control and they do not automatize or do anything else (for example, to insert data about the same user in two tables I need to use two separate insert statements and the foreign key will not help to make this different or automatic in some way).
Fine. Here is what I want to do: I want to use Sequelize to insert, update and retrieve data altogether from all the related tables at once and I have absolutely no idea on how to do that. For example, if a user registers, I want to be able to insert the data in the table "A" containing some user information and in the same task insert in the table B some other data (like the user's settings in the dedicated table or whatever). Same with retrievals, I want to be able to get an object (or array) with all the related data from different tables fitting in the criteria I want to find by.
Sequelize documentation covers the things in a way that every thing depends on the previous one, and Sequelize is pretty bloated with a lot of stuff I do not need. I do not want to use .sync(). I do not want to use migrations. I have the structure of my database created already and I want Sequelize to attach to it.
Is it possible insert and retrieve several rows related at the same time and getting / using a single Sequelize command / object? How?
Again, by "related data" I mean data "linked" by sharing the same foreign key.
Is it possible insert and retrieve several rows related at the same
time and getting / using a single Sequelize command / object? How?
Yes. What you need is eager loading.
Look at the following example
const User = sequelize.define('user', {
username: Sequelize.STRING,
});
const Address = sequelize.define('add', {
address: Sequelize.STRING,
});
const Designation = sequelize.define('designation', {
designation: Sequelize.STRING,
});
User.hasOne(Address);
User.hasMany(Designation);
sequelize.sync({ force: true })
.then(() => User.create({
username: 'test123',
add: {
address: 'this is dummy address'
},
designations: [
{ designation: 'designation1' },
{ designation: 'designation2' },
],
}, { include: [Address, Designation] }))
.then(user => {
User.findAll({
include: [Address, Designation],
}).then((result) => {
console.log(result);
});
});
In console.log, you will get all the data with all its associated models that you want to include in the query
I'm using sails.js and sails-MySQL and I want to connect to a MySQL database. I have tables, functions, and procedures in my workbench. now I want to know that is it necessary to create model files and define my schema again?
Yes, you can connect to your DB without defining models. However bare in mind that you will have to write raw queries every time. So first you need to define your DB connection in your datastores.js file. Then you can do the following in some of your controllers when you want to get something from your DB (say you have a table users and you want to get all of them):
var myDBStore = sails.getDatastore(); //gets the default datastore.
var query = "SELECT * FROM users;";
myDBStore.sendNativeQuery(query).exec(function (err, nativeResult) {
if (err) {
return res.send(err);
}
return res.send(nativeResult.rows);
});
or using the modern way in an async function:
var myDBStore = sails.getDatastore(); //gets the default datastore.
var query = "SELECT * FROM users;";
var nativeResult;
try {
nativeResult = await myDBStore.sendNativeQuery(query);
} catch (err) {
return res.send(err);
}
return res.send(nativeResult.rows);
More info here: https://sailsjs.com/documentation/reference/waterline-orm/datastores in section "Using datastores without a model"
Currently, I am building a web app with nodejs + mysql and sequelize as ORM. I want to create some views like we do in mysql, but I can't find any option in Sequelize to create views.
Is there any ORM where it's possible to create views? Or is it possible to do it with sequelize?
There are no builtin methods for managing views in Sequelize, but you can create them using plain SQL queries and manage them with normal Sequelize models.
If you're using umzug for your migrations as recommended by the Sequelize docs, you can create your view using a migration similar to this:
const view_name = 'my_view';
const query = '<SQL QUERY THAT RETURNS YOUR VIEW>';
module.exports = {
up: function (database, Sequelize) {
return database.query(`CREATE VIEW ${view_name} AS ${query}`);
},
down: function (database, Sequelize) {
return database.query(`DROP VIEW ${view_name}`);
}
}
For view changes or updates, you should use the CREATE OR REPLACE VIEW syntax to ensure you can roll back your schema changes - avoid the tempation to DROP the old view and CREATE a new one!
const view_name = 'my_view';
const original_query = '<SQL QUERY THAT RETURNS YOUR VIEW>';
const new_query = '<SQL QUERY THAT RETURNS YOUR UPDATED VIEW>';
module.exports = {
up: function (database, Sequelize) {
return database.query(`CREATE OR REPLACE VIEW ${view_name} AS ${new_query}`);
},
down: function (database, Sequelize) {
return database.query(`CREATE OR REPLACE VIEW ${view_name} AS ${original_query}`);
}
}
The exact code snippets will, of course, vary depending on how you've been setting up migrations so far.
Once your migration is all set, create a Sequelize model representing your view schema as usual, using the view name as your table name. All of the find family functions should work as expected, while update, delete, and create should be expected to fail.
You can reference the Sequelize docs for raw queries, and this example repo for using Umzug with Sequelize. The only formal documentation I can find for Umzug itself is on its NPM page.
By below reference I understood how map many to many with a relationship table
http://sequelizejs.com/docs/latest/associations#many-to-many
User = sequelize.define('User', { user_name : Sequelize.STRING})
Project = sequelize.define('Project', { project_name : Sequelize.STRING })
UserProjects = sequelize.define('UserProjects', {
status: DataTypes.STRING
})
User.hasMany(Project, { through: UserProjects })
Project.hasMany(User, { through: UserProjects })
But how to query Project 's of a User
I Tried like
User.find({where:{id:1},include,[UserProjects]})
User.find({where:{id:1},include,[Projects]})
User.find({where:{id:1},include,[UserProjects]})
User.find({where:{id:1},include,[Projects]})
But i dont get results
Sequelize created table like below
users(id,name)
projects(id,project_name)
userprojects(id,UserId,ProjectId)
I tried https://github.com/sequelize/sequelize/wiki/API-Reference-Associations#hasmanytarget-options
User.find({where:{id:1}}).success(function(user){
user.getProjects().success(function (projects) {
var p1 = projects[0] // this works fine but 2 queries required. I expect in single find. without getProjects
p1.userprojects.started // Is this project started yet?
})
})
How to get all the projects of a USER ??
You should be able to get all of the properties of the user in two different ways: using includes and getting the projects from a user instance.
Using includes the code you submitted above is almost right. This method will only make one query to the database using the JOIN operation. If you want all of the users with their corresponding projects, try:
User.findAll({include: [Project]})
You can also get the projects directly from a user instance. This will take two queries to the database. The code for this looks like
User.find(1).then(function(user) {
user.getProjects().then(function(projects) {
// do stuff with projects
});
});
Does this work for you?