Not store updatedAt with sequelize model - mysql

When I store models in my MySQL DB, they are immutable. As a result I can see the need for the createdAt column in my tables, but I don't need the redundant updatedAt column. Can I configure sequelize not to store updatedAt time and then can I drop the column from my table?

Looking at the documentation regarding your situation
If you want sequelize to handle timestamps, but only want some of them, or want your timestamps to be called something else, you can override each column individually:
const Foo = sequelize.define('foo', { /* bla */ }, {
// don't forget to enable timestamps!
timestamps: true,
// I don't want createdAt
createdAt: false,
// I want updatedAt to actually be called updateTimestamp
updatedAt: 'updateTimestamp',
// And deletedAt to be called destroyTime (remember to enable paranoid for this to work)
deletedAt: 'destroyTime',
paranoid: true
})
So in the above example, just set timestamps to be true but then createdAt to be false

Found my own answer at http://docs.sequelizejs.com/manual/tutorial/models-definition.html#configuration, I should use updatedAt: false in my model definition.

Related

Sequelize - Enable paranoid: true on query level while its false on the defined Model

So lets say I have a Sequelize model defined with paranoid defaulting to "false":
const Country = sequelize.define('Country', {
name: {
type: DataTypes.STRING,
defaultValue: '',
},
code: {
type: DataTypes.STRING,
defaultValue: '',
},
currency: {
type: DataTypes.STRING,
defaultValue: '',
},
languages: {
type: DataTypes.STRING,
defaultValue: '',
},
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
deletedAt: DataTypes.DATE
});
Now when I invoke Model.destroy() on any records of Country table, the records would be hard deleted. Enabling paranoid: true on the Model definition would result in soft deletes.
I wanted to achieve the opposite of this. Where, the paranoid flag on model definition is set to false and we need to explicitly define a flag on the Model.destroy() method to soft-delete an entry and by default all records would be hard deleted.
I tried to sift through the documentation in order to find something but couldn't. Would appreciate any help I can get in case I missed something or if there's a workaround.
Why I need to do this? Some background
I joined a project with about 100+ defined models (even more) on which the paranoid flag is not defined and is false by default. Thankfully, the createdAt, updatedAt and deletedAt timestamps are defined explicitly. But any call to the Model.destroy() function results in a hard delete.
I need to introduce the functionality of a soft delete without changing any model definitions (because that would result in unintended consequences). Again, thankfully, the Model.destroy() method is wrapped in a function which is used in the entire codebase.
I was thinking of introducing an optional flag on this wrapper function which would indicate whether the delete needs to be soft or hard. So the default functionality would be hard delete unless explicitly specified to be a soft delete.
Worst case solution I can think of is that in case soft delete is required, then replace the destroy method with a raw query where I update the deletedAt timestamp manually. But hoping to find cleaner solutions than this :)
The simplest solution would be to use force: false option in case of soft-delete and force: true in case of hard-delete:
async function wrappedDestroy(item, isSoftDelete) {
await item.destroy({ force: !isSoftDelete })
}
Of course, you need to turn on paranoid: true in the model because it also affects all findAll/findOne queries as well (I suppose you wish to hide all soft-deleted records from findAll/findOne by default).

Enable only createdAt time stamp and ignore updatedAt timestamp in Sequelize

I am trying to create some records into table with only the createdAt column filled. I want the updatedAt column to not exist how ever when i create a model it automatically generates the createdAt and updatedAt timestamps.
I tried to use timestamps : false but the createdAt column contains empty values.
const MyTable = sequelize.define(
'my_table',
{
id: {
type: DataTypes.INTEGER(11),allowNull: false,
primaryKey: true,autoIncrement: true,
},
person_name: {type: DataTypes.STRING(255),allowNull: false},
created: {type: DataTypes.DATE,allowNull: true},
},
{
tableName: 'my_table',
timestamps: false,
createdAt: 'created',
},
);
Is it possible to fix this issue in the model itself without doing any change in the query ?
According to the documentation on Init, you'll wanna leave the timestamps feature turned on, but configure your model to not use updatedAt.
Here's an edited version of the options object in your sample code that should give you what you are looking for:
{
tableName: 'my_table',
updatedAt: false,
}
NB: The docs say "Timestamps must be true", which might indicate why it wasn't working the way it is in the sample you provided.
Cheers!

Sails.js: how to do updatedDate for records?

I am trying to figure out how to get an updatedDate record to save into entries on my basic MySQL-enabled CRUD application. I have this in my models/user.js for the createdDate:
createdData: {
type: 'string',
columnType: 'datetime'
}
I wanted something like this for the updatedDate:
createdData: {
type: 'string',
columnType: 'datetime',
value: date(),
}
According to the documentation, there is a function within Sails.js for updatedAt but this doesn't specify which field it sends that date(); calculation to. Is there something I am missing for creating an updatedAt column for updated records?
createdAt and updatedAt (along with ID) are base attributes that are included in all of your models by default. That means updatedAt is its own field created automatically by Sails.
updatedAt simply marks the most recent time any changes were made to that entry.
If you want to change the format this data is saved in you can do that in your config/models.js file.

A Sequelize column that cannot be updated

Is it possible to create a column on a MySQL table using Sequelize that can be initialized when creating a new row, but never updated?
For example, a REST service allows a user to update his profile. He can change any field except his id. I can strip the id from the request on the API route, but that's a little redundant because there are a number of different models that behave similarly. Ideally, I'd like to be able to define a constraint in Sequelize that prevents the id column from being set to anything other than DEFAULT.
Currently, I'm using a setterMethod for the id to manually throw a ValidationError, but this seems hackish, so I was wondering if there's a cleaner way of doing this. Even worse is that this implementation still allows the id to be set when creating a new record, but I don't know a way around this as when Sequelize generates the query it calls setterMethods.id to set the value to DEFAULT.
return sequelize.define('Foo',
{
title: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
notEmpty: true
}
}
},
{
setterMethods: {
id: function (value) {
if (!this.isNewRecord) {
throw new sequelize.ValidationError(null, [
new sequelize.ValidationErrorItem('readonly', 'id may not be set', 'id', value)
]);
}
}
}
}
);
Look at this Sequelize plugin:
https://www.npmjs.com/package/sequelize-noupdate-attributes
It adds support for no update and read-only attributes in Sequelize models.
In your specific case, you could configure the attribute with the following flags:
{
title: {
type: DataTypes.STRING,
allowNull: false,
unique : true,
noUpdate : true
}
}
That will allow the initial set of the title attribute if is null, and then prevent any further modifications once is already set.
Disclaimer: I'm the plugin author.

Grails: text instead of varchar

I need the MySQL column type for the String field in my Domain class to be TEXT or VARCHAR(3000), but nothing I try seems to work - it remains VARCHAR(255). I've tried
static mapping = {
longString type: 'text'
}
and
static mapping = {
longString sqlType: 'text'
}
and
static constraints = {
longString (blank: true, nullable: true, maxSize: 3000)
}
and
static constraints = {
longString (blank: true, nullable: true, size: 0..65535)
}
MySQL Server version 5.0.95, Grails 2.4.3.
I'm totally mystified and would appreciate any help..
You need to define the type of the column in the mapping block rather than constraints. Assuming the name of the property is longString, add this
static mapping = {
longString type: 'text'
}
This will create a column with a MySQL type of longtext.
To verify that this works, try dropping your database, create a new (empty) database, restart the app and check the type of the column that is created. See this example for reference.