My current models:
let Book = sequelize.define('book', {
title: Sequelize.STRING,
author: Sequelize.STRING,
...
});
let Recommendation = sequelize.define('recommendations', {
reasoning: Sequelize.STRING,
rating: Sequelize.FLOAT,
});
Book.belongsToMany(Recommendation, {through: 'bookrecommendation'});
Recommendation.belongsToMany(Book, {through: 'bookrecommendation'});
When executing code below method addRecommendation to add Recommendation for Book I get an error Error: Invalid value [object Promise]
Book.findOrCreate({
where: { id: '1' }, defaults: {
author: 'test',
title: 'test'
}
})
.spread(function (b, createdBook) {
const rec = Recommendation.create(
{
reasoning: 'test',
rating: 1
});
b.addRecommendation(rec).then((result) => {
}, (error) => {
console.log(error);
})
}
The issue here is that rec is a promise.
This should solve the issue
Book.findOrCreate({ where: { id: '1' }, defaults: {
author: 'test',
title: 'test'
}}).spread(function (b, createdBook) {
Recommendation.create({
reasoning: 'test',
rating: 1
}).then((rec) => {
b.addRecommendation(rec).then((result) => {}, (error) => {
console.log(error);
})
})
Related
How can I bulk update records using sequelize.js. All of the time, I will be having only 150 users to update. In this case how do I find unique records to udpate in MySql ? At the moment update of record is not happening
1.email field is unique
2.existing records if changed need to be updated
3.new records need to be inserted
server.js
const manageNomineesSchema = require('./server/models/managenominees');
const ManageNomineesModel = manageNomineesSchema(sequelize, DataTypes);
app.post('/service/managenominees', upload.single('file'), async (req, res, next) => {
try {
if(req.file){
let filePath = req.file.path;
fs.createReadStream(filePath)
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', async () => {
console.log(results);
const allNominees = results.map(
nominees => {
return {
name: nominees.name,
email: nominees.email
}
});
const emailCount = await ManageNomineesModel.count({ col: 'email' });
if(emailCount == 0){
await ManageNomineesModel.bulkCreate(allNominees);
} else {
await ManageNomineesModel.bulkCreate(allNominees,
{ updateOnDuplicate: ["email"] },
{attributes: { exclude: ['createdAt'] }
})
}
res.status(200).json({ message: "Nominees inserted successfully !"});
});
}
} catch (e) {
res.status(500).json({ fail: e.message });
}
});
managenominees.js
module.exports = (sequelize, DataTypes) => {
const managenominees = sequelize.define('managenominees', {
id: {
type: DataTypes.INTEGER(10),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(200),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false
},
access: {
type: DataTypes.STRING(10),
allowNull: true
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW
}
}, {
timestamps: true,
tableName: 'managenominees'
});
return managenominees;
};
After adding a PK inside the where clause where: { id: ['id']}, it started updating the records against the column updateOnDuplicate: ["name"]
const emailCount = await ManageNomineesModel.count({ col: 'email' });
if(emailCount == 0){
await ManageNomineesModel.bulkCreate(allNominees);
res.status(200).json({ message: "Nominees inserted successfully !"});
} else {
await ManageNomineesModel.bulkCreate(allNominees,
{ updateOnDuplicate: ["name"],
where: { id: ['id']}
});
res.status(200).json({ message: "Nominee records updated successfully !"});
}
I have two model that are belongs to each other (order_items.js & products.js) productId as a foreign key in order_items, code as below:
order_items.js
const { DataTypes } = require('sequelize')
const db_config = require(`../config/config`)
const Product = require('./product')
const OrderItem = db_config.define('order_item', {
productId : { type: DataTypes.INTEGER, allowNull:false, references: {model: Product, key: 'id'} },
quantity: { type: DataTypes.INTEGER }
}, {
freezeTableName: true
})
module.exports = OrderItem
product.js
const { DataTypes } = require('sequelize')
const db_config = require(`../config/config`)
const Category = require('./category')
const Product = db_config.define('product', {
productName : { type: DataTypes.STRING, allowNull:false },
productPrice: { type: DataTypes.INTEGER, allowNull:false },
productDescription: { type: DataTypes.STRING, allowNull:true },
productImage: { type: DataTypes.STRING, allowNull:true },
productStock: { type: DataTypes.INTEGER, validate: { min: 0 }, defaultValue: 0, allowNull: false },
CategoryId: { type: DataTypes.INTEGER, allowNull:false, defaultValue: 1, references: {model: Category, key: 'id'}}
}, {
freezeTableName: true
})
module.exports = Product
order_routes.js
router.get('/', async (req, res) => {
try {
const dataList = await OrderItem.findAll({include: [{model:Product, required:true}]})
res.send({
status: "success",
message: "data found",
data: dataList
})
} catch (err) {
res.send({
status: "failed",
message: err})
}
})
Result in postman
Can anyone help please? what I'm trying to do is that when I get the order_item, it also get the products refers to the id of the products
Where are the associations in the model definition? I see a reference on column field but you also needs to do below definitions seperately
Inside OrderItem Model File
OrderItem.associate = models => {
OrderItem.belongsTo(Product, {as: "product", foreignKey: "productId", sourceKey: "id"});
};
Inside Products Model File
Product.associate = models => {
Product.hasMany(OrderItem, {as: "orders", foreignKey: "productId", sourceKey: "id"});
};
Also I would suggest you to store price in OrderItem collection as well so in case in future when the product price changes your past order data is not incorrect.
I want to update the wallet table when I deposit an amount in the wallet.
My code is like this:
model wallet.js
'use strict';
module.exports = (sequelize, DataTypes) => {
var Model = sequelize.define('wallet', {
id: {
type: DataTypes.INTEGER,
field: 'id',
primaryKey: true,
autoIncrement: true
},
cid: {
type: DataTypes.STRING,
field: 'cid'
},
deposit: {
type: DataTypes.INTEGER,
field: 'deposit'
},
withdrawal: {
type: DataTypes.INTEGER,
field: 'withdrawal'
},
available: {
type: DataTypes.INTEGER,
field: 'available',
},
comments: {
type: DataTypes.DATE,
field: 'comments'
},
online: {
type: DataTypes.STRING,
field: 'online'
}
}, {
tableName: 'wallet',
timestamps: false
});
Model.associate = function (models) {
this.orders = this.hasOne(models.orders, {
as: 'orders',
foreignKey: 'wid'
});
};
Model.prototype.toWeb = function (pw) {
let json = this.toJSON();
return json;
};
return Model;
};
here the wallet deposit is happening here i am using set method to update the wallet
walletcontroller.js
const deposit = async function (req, res) {
res.setHeader('Content-Type', 'application/json');
let err, wallet, existingWallet;
let wallet_info = req.body;
[err, existingWallet] = await to(Wallet.findAll({
limit: 1,
where: {
cid: wallet_info.cid,
},
order: [
['id', 'DESC']
]
}));
[err, wallet] = await to(Wallet.set(wallet_info, {
limit: 1,
where: {
cid: wallet_info.cid,
},
order: [
['id', 'DESC']
]
}));
if (err) return ReE(res, err, 422);
if (existingWallet[0] != 'undefined') {
wallet.available = existingWallet[0].available + wallet_info.deposit;
wallet.comments = new Date();
} else {
wallet.available = wallet_info.deposit;
wallet.comments = new Date();
}
console.log("avalible balance:" + wallet.available);
[err, wallet] = await to(wallet.save());
if (err) return ReE(res, err, 422);
return ReS(res, {
wallet: wallet.toWeb()
}, 201);
}
module.exports.deposit = deposit;
please help me out how to update the wallet... when i am callig api here my err msg looks like this
Executing (default): SELECT `id`, `cid`, `deposit`, `withdrawal`, `available`, `comments`, `online` FROM `wallet` AS `wallet` WHERE `wallet`.`cid` = '33' ORDER BY `wallet`.`id` DESC LIMIT 1;
Error:
Uncaught Error { filename: '\\cl-api-master\\controllers\\WalletController.js',
line: 67,
row: 37,
message: 'Wallet.set is not a function',
type: 'TypeError',
stack: 'TypeError: Wallet.set is not a function\n at deposit (E:\\cl-api-master\\controllers\\WalletController.js:67:37)\n at <anonymous>',
arguments: undefined }
POST /v1/wallet/deposit - - ms - -
For Edition, you can simply use -
data.update = await Wallet.update(
{
available: available,
comments: new Date()
},
{
where: { cid: wallet_info.cid }
}
);
available variable can be set using if else condition afterward running above update query.
Currently using ExpressJS as the framework to create a small CMS system but currently running into a problem. I am trying to create a model for a table called 'roles' but when I add it to my database file to be included, I get the following error once I run 'node app.js'
Unhandled rejection TypeError: Cannot read property 'id' of undefined
at Object.mapValueFieldNames (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\sequelize\lib\utils.js:232:19)
at Promise.try.then.then (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\sequelize\lib\model.js:2393:37)
at tryCatcher (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:512:31)
at Promise._settlePromise (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:569:18)
at Promise._settlePromise0 (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:614:10)
at Promise._settlePromises (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:694:18)
at _drainQueueStep (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:138:12)
at _drainQueue (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:131:9)
at Async._drainQueues (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:147:5)
at Immediate.Async.drainQueues (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:17:14)
at runCallback (timers.js:810:20)
at tryOnImmediate (timers.js:768:5)
at processImmediate [as _immediateCallback] (timers.js:745:5)
If I do not include the model in the database init file, it runs just fine. The idea is to then use a relationship to pair the two. I do not plan on having permissions assigned, just using roles. The migration file is setup the same as the model. I was assuming by matching how the user model was setup, the roles model would work as well. But now I am unsure what is going on.
Users
'use strict';
const
Promise = require('bluebird'),
bcrypt = Promise.promisifyAll(require('bcrypt'))
;
module.exports = (sequelize, DataTypes) => {
const users = sequelize.define('users', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
username: {
type: DataTypes.STRING,
notEmpty: true,
unique: true
},
password: {
type: DataTypes.STRING,
notEmpty: true
},
role: {
type: DataTypes.INTEGER(2).UNSIGNED,
validate: {
isNumeric: true
}
},
steamid: {
type: DataTypes.STRING(17),
validate: {
len: 17
}
},
link: {
type: DataTypes.STRING,
validate: {
isUrl: true
}
},
last_login: DataTypes.DATE
},
{
hooks: {
beforeCreate: function(user, options) {
if (!user.changed('password')) {
return sequelize.Promise.reject('not modified');
}
return bcrypt.hash(user.password, 10).then(hash => {
return user.password = hash;
}).catch(err => {
return sequelize.Promise.reject(err);
});
},
beforeUpdate: function(user, options) {
if (!user.changed('password')) {
return sequelize.Promise.reject('not modified');
}
return bcrypt.hash(user.password, 10).then(hash => {
return user.password = hash;
}).catch(err => {
return sequelize.Promise.reject(err);
});
}
}
});
users.prototype.generateHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(10));
};
users.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
users.sync({force: false}).then(() => {
return users.findOrCreate({
where: {
id: 1,
username: 'Admin'
},
defaults: {
username: 'Admin',
password: 'admin123',
role: 1,
steamid: parseInt(12345678901234567),
link: 'https://www.example.com/user_profile.php?userID=1171981'
}
});
});
return users;
};
Roles
'use strict';
module.exports = (sequelize, DataTypes) => {
const roles = sequelize.define('roles', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: DataTypes.STRING,
slug: DataTypes.STRING
}, {
timestamps: false
});
let role = [];
role.push([
{ name: 'Admin', slug: 'admin'},
{ name: 'Staff', slug: 'staff'},
{ name: 'Trainer', slug: 'trainer'},
{ name: 'Captain', slug: 'captain'},
{ name: 'Monkey', slug: 'monkey'}
]);
roles.sync({force: false}).then(() => {
return roles.bulkCreate(role);
});
return roles;
};
Init
const
config = require('../config/database'),
Sequelize = require('sequelize'),
sequelize = new Sequelize(config),
db = {}
;
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.users = require('./models/users')(sequelize, Sequelize);
db.roles = require('./models/roles')(sequelize, Sequelize);
module.exports = db;
I have two models tables, like
Project = Sequelize.define('Project',{
name: Sequelize.STRING
});
Task = Sequelize.define('Task',{
name:Sequelize.STRING,
status: Sequelize.BOOLEAN,
deadline: Sequelize.DATE,
from_name: Sequelize.STRING,
ProjectId: Sequelize.INTEGER
});
I need to find all records from two tables. How do I perform this query in Sequelize?
SELECT * FROM mydb.Projects
LEFT JOIN mydb.Tasks ON Projects.id = Tasks.Project_id
I using:
exports.list = function (req, res) {
Project.hasMany(Task,{ foreignKey: { allowNull: false }, onDelete: 'CASCADE' });
Project.all({
include: [{
model: Task,
required:false,
where:{ProjectId: Sequelize.col('Project.id')}
}]
})
.then(function (projects) {
res.render('TODOList', {title: 'TODO', projects: projects || [] });
console.log(projects);
})
.catch(function (err) {
if (err) {
res.render('TODOList', {title: 'TODO List'});
}
});
};
but I get records only from Project, like:
Project {
dataValues: {
id: 5,
name: 'pr2',
createdAt: 2017-08-20T07:03:09.000Z,
updatedAt: 2017-08-20T07:41:47.000Z,
Tasks: [Object]
}
}
How I can get records Task (Project.dataValues.Task)?
So models are (say it: db/models.js):
const
Project = Sequelize.define(
'Project',
{
name: Sequelize.STRING
}),
Task = Sequelize.define(
'Task',
{
name: Sequelize.STRING,
status: Sequelize.BOOLEAN,
deadline: Sequelize.DATE,
from_name: Sequelize.STRING,
ProjectId: Sequelize.INTEGER
});
// relations must be defined once in model definition part (not like You do in every request
Project.hasMany(Task, {foreignKey: {allowNull: false}, onDelete: 'CASCADE'});
Task.belongsTo(Project);
module.exports = {Project, Task};
And in Your router's handler (say it routes/projects/list.js):
const Sequelize = require('sequelize');
const {Project, Task} = require('../../db/models');
module.exports.list = (req, res) => {
const query = {
include: [{
model: Task,
as: 'tasks',
required: false
}]
};
Project
.all(query)
.then(function (projects) {
// it's not recommended, but You insist to get read of model instances and have normal array of objects
projects = projects ? projects.map(project => project.toJSON()) : [];
res.render(
'TODOList',
{
title: 'TODO',
projects
});
console.log(projects);
})
.catch(function (err) {
console.error(err);
res.render('TODOList', {title: 'TODO List'});
});
};
but since sequelize returns array of sequelize model instances - it's normal to have dataValues don't worry just use as usual:
for(let project of projects) {
console.log(project.tasks[0].name);
}