sequelize posting NULL in database(MySql) - mysql

module.exports = function (sequelize, Sequelize) {
var User = sequelize.define('user', {
id: { autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER },
firstname: { type: Sequelize.STRING, notEmpty: true },
lastname: { type: Sequelize.STRING, notEmpty: true },
//username: { type: Sequelize.TEXT },
//about: { type: Sequelize.TEXT },
mobileno: { type: Sequelize.STRING },
email: { type: Sequelize.STRING, validate: { isEmail: true } },
password: { type: Sequelize.STRING, allowNull: false },
last_login: { type: Sequelize.DATE },
//status: { type: Sequelize.ENUM('active', 'inactive'), defaultValue: 'active' }
});
return User;
}
Everything else is posting fine but mobileno is being posted as null in database.
I tried setting mobile no as allowNull = false but that gives me an error.
I also tried changing string to text but that didn't help either...
this is the eroor after adding allowNull=false..

After checking the documentation your code is working normally.
// setting allowNull to false will add NOT NULL to the column, which means an error will be
// thrown from the DB when the query is executed if the column is null. If you want to check that a value
// is not null before querying the DB, look at the validations section below.
title: { type: Sequelize.STRING, allowNull: false },
Before saving to the db, you need to validate your info to make sure that mobileno is not null. Once you have a value for mobileno you can save it to the db.

Your problems is in your data not in your sequelize model
Based on your question I think you send the empty value for mobileno field
About AllowNull parameter: when you will set the false it's means sequelize will return error if you will not pass parameter (which happens in your case)
By default AllowNull value is true
My suggestion is to check you data before insert query also when you will run create command using sequelize check console it's will show you insert into sql format

Related

ValidationError: "column" is not allowed to be empty on null column

When trying to set passwordResetToken to null I get not allowed to be empty errors. If I manually run the query against the db, no trouble.
The full code to update user is as follows:
let user = await this.usersRepository.getById(userId);
// ...
const userData = {
encryptedPassword: await bcrypt.hash(
newPasswd,
Number(process.env.BCRYPT_ROUNDS)
),
passwordResetToken: null,
passwordResetExpires: null
};
user = await this.usersRepository.update(user.id, userData);
I have a model defined as such
const User = sequelize.define(
'user',
{
forename: DataTypes.STRING,
surname: DataTypes.STRING,
email: DataTypes.STRING,
encryptedPassword: DataTypes.STRING,
passwordResetToken: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
validate: {
notEmpty: false
}
},
passwordResetExpires: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null,
validate: {
isDate: true
}
}
},
{
classMethods: {
associate() {
// associations can be defined here
}
}
}
);
As you can see allowNull is true, defaultValue is null and validate: notEmpty set to false. What am I missing?
Using sequelize v4.42.0
Dialect 'mysql'
This was actually caused by another part of my validation by npm module structure.
I had to set empty to true in my schema like this:
passwordResetToken: {
type: String,
required: false,
empty: true
},

Sequelize "unique: true" making same unique key two times with different keyname

Test1: Adding "unique: true" in email attribute.
Test2: Adding "unique: {args: true, msg: "xxxxxx"}" in email attribute.
Using Sequelize: 4.7.5 & MySQL: 5.7.19
I'm expecting there will be one index for both the test cases.
But I'm getting two indexes for the Test1. Both indexes are having same column but different keyname.
Is it a bug or I'm doing anything wrong?
Try the following model defs.
Test1 = {
id: {
type: Sequelize.INTEGER.UNSIGNED,
primaryKey: true,
autoIncrement: true
},
emailId: {
type: Sequelize.STRING,
unique: true,
allowNull: false,
validate: {
isEmail: {
args: true,
msg: 'Invalid email id.'
}
}
}
}
Test2 = {
id: {
type: Sequelize.INTEGER.UNSIGNED,
primaryKey: true,
autoIncrement: true
},
emailId: {
type: Sequelize.STRING,
unique: {
args: true,
msg: 'This email id is already registered.'
},
allowNull: false,
validate: {
isEmail: {
args: true,
msg: 'Invalid email id.'
}
}
}
}
Use string instead boolean.
I found my answer here: https://github.com/sequelize/sequelize/issues/6134
Normal index with string

sequelize.js TIMESTAMP not DATETIME

In my node.js app I have several models in which I want to define TIMESTAMP type columns, including the default timestamps created_at and updated_at.
According to sequelize.js' documentation, there is only a DATE data type. It creates DATETIME columns in MySQL.
Example:
var User = sequelize.define('User', {
... // columns
last_login: {
type: DataTypes.DATE,
allowNull: false
},
...
}, { // options
timestamps: true
});
Is it possible to generate TIMESTAMP columns instead?
Just pass in 'TIMESTAMP' string to your type
module.exports = {
up: function (queryInterface, Sequelize) {
return queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
created_at: {
type: 'TIMESTAMP',
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: false
},
updated_at: {
type: 'TIMESTAMP',
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: false
}
});
}
};
According to the Sequelize Documentation, you can set a defaultValue of Sequelize.NOW to create a timestamp field. This has the effect but relies on Sequelize to actually populate the timestamp. It does not create a "CURRENT_TIMESTAMP' attribute on the table.
var Foo = sequelize.define('Foo', {
// default values for dates => current time
myDate: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW
}
});
So, this does accomplish the end goal of having a timestamp field, but it is controlled through Sequelize and not through the actual database engine.
It also appears to work on databases that do not have a timestamp functionality, so that may be a benefit.
Reference URL: http://sequelize.readthedocs.org/en/latest/docs/models-definition/#definition
In my case i create model like below
module.exports = (sequelize, type) => {
return sequelize.define('blog', {
blogId: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true
},
text: type.STRING,
createdAt:{
type: 'TIMESTAMP',
defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: false
},
updatedAt:{
type: 'TIMESTAMP',
defaultValue: sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'),
allowNull: false
}
})
}
You can also use the moment for creating a timestamp:
const moment = require('moment-timezone');
createdAt: {
type: DataTypes.NOW,
allowNull: false,
defaultValue: moment.utc().format('YYYY-MM-DD HH:mm:ss'),
field: 'createdAt'
},
instead of
type: DataTypes.DATE,
use below code
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('NOW'),
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('NOW'),
},
What I did with sqLite is extended DataTypes with my custom sql logic for TIMESTAMP and it worked fine. I'm not 100% sure how the sql syntax should look for MySQL but my guess it's something similar to what I have. Look at example:
function (sequelize, DataTypes) {
var util = require('util');
var timestampSqlFunc = function () {
var defaultSql = 'DATETIME DEFAULT CURRENT_TIMESTAMP';
if (this._options && this._options.notNull) {
defaultSql += ' NOT NULL';
}
if (this._options && this._options.onUpdate) {
// onUpdate logic here:
}
return defaultSql;
};
DataTypes.TIMESTAMP = function (options) {
this._options = options;
var date = new DataTypes.DATE();
date.toSql = timestampSqlFunc.bind(this);
if (!(this instanceof DataTypes.DATE)) return date;
DataTypes.DATE.apply(this, arguments);
};
util.inherits(DataTypes.TIMESTAMP, DataTypes.DATE);
DataTypes.TIMESTAMP.prototype.toSql = timestampSqlFunc;
var table = sequelize.define("table", {
/* table fields */
createdAt: DataTypes.TIMESTAMP,
updatedAt: DataTypes.TIMESTAMP({ onUpdate: true, notNull: true })
}, {
timestamps: false
});
};
All you need to do for MySQL is to change SQL type generation in timestampSqlFunc function, so for example defaultSql variable would be 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP'

Set safe-deleting mode for relations table in Sequelize.js

So, assume we have that Sequelize model:
var User = sequelize.define("User", {
id: {
type: DataTypes.STRING(45),
allowNull: false,
primaryKey: true
},
password: {
type: DataTypes.STRING(60),
allowNull: false
},
email: {
type: DataTypes.STRING(45),
allowNull: false,
unique: true
},
firstName: {
type: DataTypes.STRING(45),
allowNull: true,
defaultValue: null
}
},
{
tableName: 'profiles',
classMethods: {
associate: function(models) {
User.belongsToMany(User, {through: 'friends', as:'friend'});
}
}
});
after calling associate() method, it will create an extra table friends with columns userId, friendId, createdAt and updatedAt. The case is I need to use this table with safe-deleting mode, in other words, I have to add 'deleted' column somehow. I tried to use paranoid: true in belongsToMany's attributes, didn't work. Is there any ways to do it?
Maybe you can create an model/table which name is Friend. And you can set paranoid: true in that model. And when you deleted an User, it keeps User's friend relation was keeping in that model.
I hope it works. :)

Is there no option to map the column name in sequelize model

I have a given database with long, cumbersome columnnames. Isn't there any way to map the tablenames to shorter and more descriptive propertyNames in the model ?
something like
var Employee = sql.define('Employee', {
id : {type : Sequelize.INTEGER , primaryKey: true, map : "veryLongNameForJustTheId"}
},{
tableName: 'cumbersomeTableName',
timestamps: false
});;
id : {
field: 'some_long_name_that_is_terrible_thanks_dba_guy',
type : Sequelize.INTEGER ,
primaryKey: true
}
Specify a 'field' attribute ... Like that ^
You can specify a table name by supplying the name as the first parameter to the define() call. For example:
var User = sequelize.define(
'a_long_cumbersone_users_table_name',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true
},
name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
rememberToken: {
type: Sequelize.STRING,
field: 'remember_token'
}
},
{
underscored: true,
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at'
}
);
So far the best solution I found to do this is to use getters and setters.
They will - however - not affect results in object.values or object.toJSON(). You'll need your own serialization methods if you want to use these.