I understood how to make a dynamic insert based on what properties has an object:
let job_seeker = {
username: 'j.smith',
user_type: 'job_seeker',
name: 'john smith',
email: 'j.smith#example.com',
resume: true,
resume_date_time: '2109-01-01',
salary_expectation: 100000
};
let employer = {
username: 'b.burke',
user_type: 'employer',
name: 'betty burke',
email: 'b.burke#example.com',
company_name: 'Acme Inc.',
company_profile: 'http://acme.example.com/about_us/'
};
connection.query('INSERT INTO users SET ?', job_seeker, function(error, results, fields) {
if (error) throw error;
console.log(results.insertId);
});
connection.query('INSERT INTO users SET ?', employer, function(error, results, fields) {
if (error) throw error;
console.log(results.insertId);
});
But, what if I have an object like:
user_employers = [
{
username: 'b.burke',
user_type: 'employer',
name: 'betty burke',
company_profile: 'http://acme.example.com/about_us/'
},
{
username: 'b.burke',
user_type: 'job_seeker',
name: 'john smith',
email: 'j.smith#example.com',
resume: true,
resume_date_time: '2109-01-01',
salary_expectation: 100000
},
// and so on, with dynamic properties
]
And i have to make a multiple insert or update with the object user_employers? I have to do a loop of INSERT/UPDATE query, or is there a better way?
Related
I am using the beforeCreate to encrypt password before saving to database.
When I do:
const user = await User.create({name, email, password});
res.json(user);
I see the encrypted password in response. But in the database the password is not encrypted. If I do user.reload() and then send, I see what's stored in the database(unencrypted password).
This is the model:
User.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
...
},{
sequelize,
hooks: {
beforeCreate: (user, options) => {
return bcrypt.genSalt(10)
.then(salt => {
bcrypt.hash(user.password, salt)
.then(hashedPassword => {
user.password = hashedPassword;
console.log(user.password, "FS");
return user.password;
})
.catch(err => console.log(err));
})
.catch(err => console.log(err));
}
}
})
This is the controller:
try{
const {name, email, password} = req.body;
if(isEmpty(name) || isEmpty(email) || isEmpty(password)){
res.status(400).json({errMessage: 'Enter name, email and password'});
}
const user = await User.create({name, email, password});
res.json(user); //data with encrypted password is sent, but not saved in db
}
The beforeCreate hook does not need to return a value, the return value type of the function signature as follows:
export type HookReturn = Promise<void> | void;
Besides, you forgot to add return before bcrypt.hash(user.password, salt) statement causes the beforeCreate function not to wait for the encryption asynchronous operation to complete.
Here is a working example:
import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
import bcrypt from 'bcrypt';
class User extends Model {
password!: string;
name!: string;
}
User.init(
{
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
modelName: 'users',
hooks: {
beforeCreate: (user: User) => {
return bcrypt
.genSalt(10)
.then((salt) => {
return bcrypt
.hash(user.password, salt)
.then((hashedPassword) => {
user.password = hashedPassword;
})
.catch((err) => console.log(err));
})
.catch((err) => console.log(err));
},
},
},
);
(async function() {
try {
await sequelize.sync({ force: true });
await User.create({ name: 'ab', email: 'test#gmail.com', password: '123456' });
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
The execution log:
Executing (default): DROP TABLE IF EXISTS "users" CASCADE;
Executing (default): DROP TABLE IF EXISTS "users" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "users" ("id" SERIAL , "name" VARCHAR(255) NOT NULL, "email" VARCHAR(255) NOT NULL, "password" VARCHAR(255) NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "users" ("id","name","email","password") VALUES (DEFAULT,$1,$2,$3) RETURNING *;
Check data record in the database:
node-sequelize-examples=# select * from users;
id | name | email | password
----+------+----------------+--------------------------------------------------------------
1 | ab | test#gmail.com | $2b$10$XQb89m.b6ie8ImokS6JPdurWfIH4Cq19y.XGhb7LpWYUklp5jaYh2
(1 row)
W3School tutorial on NodeJs-MySQL: SELECT cmmand does not provide output in proper format. In each row of output "RowDataPacket" word is appearing. How to avoid it?
C:\Users\Raju>node demo_db_select.js
[ RowDataPacket { id: 1, name: 'John', address: 'Highway 71' },
RowDataPacket { id: 2, name: 'Peter', address: 'Lowstreet 4' },
I used the following code:
var mysql = require('mysql');
var con = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});
con.connect(function(err) {
if (err) throw err;
con.query("SELECT * FROM customers", function (err, result, fields) {
if (err) throw err;
console.log(result);
});
});
var data = [
RowDataPacket { id: 1, name: 'John', address: 'Highway 71' },
RowDataPacket { id: 2, name: 'Peter', address: 'Lowstreet 4' }
]
This means the inside object is the instane of the class RowDataPacket. You can still simply use it like:
data[0].id // 1
data[0].name // John
data[1].name // Peter
You are executing a MySQL query and storing the selected rows and columns in result variable. Actually result is a object. So run a for loop and print all the values as I written in code.
Try this code:
var mysql = require('mysql');
var con = mysql.createConnection({ host: "localhost", user: "yourusername", password: "yourpassword", database: "mydb" });
con.connect(function(err) {
if (err) throw err;
con.query("SELECT * FROM customers", function (err, result, fields) {
if (err) throw err;
for(let i in result){
console.log("id="+result[i].id);
console.log("Name="+result[i].name);
console.log("address="+result[i].address);
}
});
});
I'm developing a MEAN stack application and I'm hung up on how to actually update a document that has been saved into the MongoDB already. I've seen that I have to use patch instead of post in my REST API paths, but it's still a little clouded to me. I want to insert a new Package into the Package JSON Array in the User JSON.
Possible Duplicate, but he's overriding a value in the array and not adding a new object into it.
My JSON Schema:
//User schema
const UserSchema = mongoose.Schema({
name: {
type: String
},
email: {
type: String,
require: true
},
username:{
type:String,
required: true
},
password:{
type:String,
required: true
},
packages: [{
from: String,
to: String,
tracking: String
}]
});
My REST API Paths
//Update
router.patch('/update', (req, res) => {
const username = req.body.username;
const packages = req.body.packages;
User.getUserByUsername(username, (err, user) => {
if(!user){
return res.json({success: false, msg: 'User not found'});
} else {
User.addPackages(user, req.body.packages, (err, user) => {
if(err){
res.json({success: false, msg:'Failed to update packages'});
} else {
res.json({success: true, msg:'update packages'});
}
})
}
});
});
My Module's:
module.exports.addPackages = function(user, packages, callback){
User.findOneAndUpdate(
{username:user.username},
{$push: {"packages" : {
"to" : packages.to,
"from" : packages.from,
"tracking" : packages.tracking
}}},
{new:true},
function(err, newPackage){
if (err) throw err;
});
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.getUserByUsername = function(username, callback){
const query = {username: username}
User.findOne(query, callback);
}
They're updating into my MongoDB, but just the object ID and not the values...
db.your_collection.update({},
{$set : {"new_field":1}},
{upsert:false,
multi:true})
I am running into an issue where my PassportJS code is issuing the exact same query (using sequelize) every time I login regardless of the username and password being inputted and as a result I am successfully logged in each time. I feel like the issue is within my localStrategy code, but I can't seem to tell.
For Instance: I am logging in with user_id=3, email=test3#gmail.com, password=test
and this is the resulting sql output:
Executing (default): SELECT `user_id`, `first_name` AS `firstName`, `last_name` AS `lastName`, `email`, `password`, `createdAt`, `updatedAt` FROM `user` AS `user` WHERE `user`.`user_id` = 1;
It shouldn't be querying user_id=1 and was never checking the values in the input because the successful redirect for the login route is being triggered.
Here is my passport configuration and routing:
var express = require('express');
var siteRoutes = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../models/db-index');
/*==== Passport Configuration ====*/
// Serialize sessions
passport.serializeUser(function(user, done) {
console.log(user.user_id + "Serializing");
done(null, user.user_id);
});
passport.deserializeUser(function(user_id, done) {
models.User.find({where: {user_id: user_id}}).then(function(user){
done(null, user);
}).error(function(err){
done(err, null);
});
});
passport.use('local', new LocalStrategy({
passReqToCallback : true,
usernameField: 'email'
},
function(req, email, password, done) {
console.log(req.body.email);
console.log(req.body.password);
//Find user by email
models.User.findOne({
email: req.body.email,
password: req.body.password
}).then(function(user) {
return done(null, user);
})
.catch(function(err) {
return done(null, false, req.flash('message', 'Email not found.'));
});
}
));
/*==== Login ====*/
siteRoutes.route('/login')
.get(function(req, res){
res.render('pages/login.hbs');
})
.post(passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/sign-up',
failureFlash: true
}));
siteRoutes.route('/sign-up')
.get(function(req, res){
res.render('pages/sign-up.hbs');
})
.post(function(req, res){
models.User.create({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password
}).then(function() {
res.redirect('/');
}).catch(function(error){
res.send(error);
})
});
module.exports = siteRoutes;
User Model:
var bcrypt = require('bcrypt-nodejs');
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('user', {
user_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: DataTypes.STRING,
field: 'first_name'
},
lastName: {
type: DataTypes.STRING,
field: 'last_name'
},
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING,
}, {
freezeTableName: true
});
return User;
}
the model variable is just a connector file for my various models. Please let me know if seeing that code would help
I have a array of data something like
var records = [
{Name: '', Id: 1},
{Name: '', Id: 2},
{Name: '', Id: 3},
{Name: '', Id: 4},
{Name: '', Id: 5},
{Name: '', Id: 6}
];
there could be thousands of items inside records array...
Ques1: Can we create a stored procedure which will accept an array of objects in mysql?
Ques2: Is there a way to bulk insert this data into mysql with Node JS?
You can bulk insert the array of records ,but before that you might need to convert it into array of arrays
I use array reduce to get an array something like this
let j=[
{Name: '', Id: 1},
{Name: '', Id: 2},
{Name: '', Id: 3},
{Name: '', Id: 4},
{Name: '', Id: 5},
{Name: '', Id: 6}
];
let values=j.reduce((o,a)=>{
let ini=[];
ini.push(a.Name);
ini.push(a.Id);
o.push(ini);
return o
},[])
console.log(values);
This will output
[["",1],["",2],["",3],["",4],["",5],["",6]]
Now inserting into the mysql database
1-Using normal callback
const con=require('./mysql.js'); //mysql connectionin mysql.js
var sql = "INSERT INTO customers (name, id) VALUES ?";
con.query(sql, [values], function (err, result) { //pass values array (from above) directly here
if (err) throw err;
console.log("Number of records inserted: " + result.affectedRows);
});
});
so the format of multiple data insert should be like [[[a,b],[b,c],[d,k]]]
2-Using promises
var Promise = require("bluebird");//for promises
const promisecon=Promise.promisifyAll(require('./mysql.js'));//
var sql = "INSERT INTO customers (name, id) VALUES ?";
promisecon.queryAsync(sql,[values]).then((result)=>{//bluebird identifies with Async
console.log(result);
}).catch(function(err){
console.log(err);
})
3-Using async await
var sql = "INSERT INTO customers (name, id) VALUES ?";
async function build() {
try {
const result =await con.queryAsync(sql,[values]);
console.log(result);
} catch (err) {
// do something
}
}
build();