How to update table with sequelize - postgresql

For example, I have db with table Users, which have some fields: (id, username).
Some later I decided add new field - email. Of course, I update model, migration and run sequelize db:migration. But nothing happened. Any ideas how to add it in Users?

Marat, if you change a migration file you had already ran into table within the database, you won't see the modifications, you have to create a new migrations file in which you're going to make references of the new field you want to create and in which table do you wanna it to be. like this for example. I decided that I need a status field in my Campaigns tables, so this is the right way to do it! hope it helps!
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.addColumn('Campaigns', 'status', {
type: Sequelize.ENUM,
values: ['Active', 'Inactive', 'Deleted'],
defaultValue: 'Active',
allowNull: false,
validate: {
notEmpty: true
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.removeColumn('Campaigns', 'status');
}
};

Related

Auto increment in postgres/sequelize

I have a Postgres database using Sequelize (node/express) as ORM. I have a table called students, in it there are columns: id and name.
In this students table, I have several registered students, but a detail: the last registered ID is 34550 and the first is 30000, they come from an import from a previous database, I need to continue counting from 34550, or that is, from the last registered student. However, when I register a student via API, the generated ID is below 30000. I know that in mysql the ID field being AUTO INCREMENT would solve it, however, as I understand it, postgres works in a different way.
How could I solve this problem?
The migration used to create the table is as follows:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('students', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
});
},
down: (queryInterface) => {
return queryInterface.dropTable('students');
},
};
Table print:
Based on Frank comment, I was able to adjust using:
SELECT setval('public.students_id_seq', 34550, true);

Sailsjs. Best way to create (and manage) indexes on sails-mongo (mongodb)

I was using sailsjs 0.12. It supported index attributes on models, also
i was using npm package Sails-hooks-mongoat to create inverse indexes and so.
It wasn't ideal, but it worked. Right now they dropped the index attribute and mongoat is currently unsafe and pending updates to work on Sails.js 1.0.
I would like to know the best approach to:
Create Indexes on new deployments.
Migrate (ensure?) indexes on deployment updates.
Since you are not allowed to run 'migrate: alter' in production (even if you try), one option is to create those index in bootstrap file ('config/bootstrap.js').
Imagine you have an User model like this:
var User = {
attributes: {
email : { type: 'string', unique: true, required: true },
username : { type: 'string', unique: true, required: true },
pin: { type: 'string'}
}
};
module.exports = User;
Then you can manually create the missing indexes like this in bootstrap file:
module.exports.bootstrap = async function(done) {
console.log("Loading bootstrap...")
if (process.env.NODE_ENV === 'test') {
}
if (process.env.NODE_ENV === 'production') {
console.log("CREATING DATABASE INDEX BY HAND")
// USER MODEL
var db = User.getDatastore().manager;
await db.collection(User.tableName).createIndex( { email: 1 }, {unique: true} );
await db.collection(User.tableName).createIndex( { username: 1 }, {unique: true} );
// PANDA MODEL
// db = Panda.getDatastore().manager;
// await db.collection(Panda.tableName).createIndex( { name: 1 }, {unique: true} );
}
// await initializeDatabase() // custom DB initialization...
return done();
};
The index are created only once, subsequent runs will not recreate those indexes.
The ensureIndex was an alias to createIndex function and it has been deprecated.
References:
Waterline manager reference
MongoDB create index reference
In development mode you can specify custom indexes in the model within Sails, or it will remove them when lifting the server and performing migration.
My (preferred) alternative approach is to manage all indexes on my own within the DB. In order to do so, you have to change the "migrate" attribute from "alter" to "safe" in models.js config file.
Note that in production mode "migrate" attribute is always set to "safe".

Custom Postgresql Sequence Nextval in SequelizeJS

How can i define sequence nextval() in sequelizeJS Model.
Is there any predefined function available for nextval() in sequelizeJS ?,
Is there any possiblity to write sequence nextval() custom function inside sequelize define model ?
In case there is someone at this point who wants to do this as well, the best way to do it I guess is using Sequelize.literal:
// on your model
const model = sequelize.define("model", {
...attributes,
customSequence: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: sequelize.Sequelize.literal("nextval('custom_sequence')")
},
})
// after create a migration for your new column
module.exports = {
up: async (queryInterface, sequelize) => {
await queryInterface.sequelize.query("CREATE SEQUENCE custom_sequence start 1020 increment 20",)
await queryInterface.addColumn('table', 'customSequence', {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: sequelize.Sequelize.literal("nextval('custom_sequence')")
})
},
down: async (queryInterface, sequelize) => {
await queryInterface.sequelize.query('DROP SEQUENCE custom_sequence')
await queryInterface.removeColumn('table', 'customSequence')
}
};
Currently there is no way in sequelize to do so, kindly refer
https://github.com/sequelize/sequelize/issues/3555
No predefined function for that. But you can make use of raw query and get nextval like
sequelize.query("SELECT nextval('sequence')", {
type: collection.Sequelize.QueryTypes.SELECT
});
I was able to do something similar as posted by #sebin and chaining the promise to my model.create(), like so:
this.sequelize
.query("SELECT max(cust_no) + 1 as 'custNo' from employees.customers", {
type: this.sequelize.Sequelize.QueryTypes.SELECT
})
.then(results => {
return results[0];
})
.then(nextPk => {
const values = Object.assign({}, newCustomer, nextPk);
return customersModel.create(values);
})
.then(newRecord => {
console.log('newRecord:', newRecord);
});
In the above case I use max +1 but the solution applies to your sequence all the same.
This works perfectly with MSSQL / MariaDB
Sequelize.literal in the "defaultValue" was the key.
I'm new to Sequelize, and luckily it lets me redefine the "id" field, which normally doesn't have to be specified in the model.
Happy day for me.
module.exports = (sequelize, Sequelize) => {
const People = sequelize.define("people", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
defaultValue: sequelize.Sequelize.literal("NEXT VALUE FOR dbo.BAS_IDGEN_SEQ")
},...

Setting the meta schemaName for a Sails model from within a controllers action?

I would like to set which schema a model is using via a controller. This is so that I would be able to use one model to populate two different schemas within a single PostgreSQL database.
I thought I would be able to access this value in the controller by using: sails.models.test.meta.schemaName = 'test2'; but it seems that this is not the case or maybe I am just going about it the wrong way.
In Sails, I have two routes:
'get /test1': 'TestController.test1',
'get /test2': 'TestController.test2'
And a relative controller:
module.exports = {
data: {
val1: 'Value 1',
val2: 'Value 2'
},
test1: function (req, res) {
Test.create( sails.controllers.test.data ).exec(function (err, result){
res.json(result);
});
},
test2: function (req, res) {
// Show the current schemaName
console.log(sails.models.test.meta.schemaName); // outputs: test1
// Trying to set the schema name
sails.models.test.meta.schemaName = 'test2';
// Trying to add a record using a different schema name
Test.create( sails.controllers.test.data ).exec(function (err, result){
res.json(result);
});
}
};
And the relative model:
module.exports = {
connection: 'postgres',
migrate: 'alter',
meta: {
schemaName: 'test1'
},
attributes: {
val1: {type: 'string'},
val2: {type: 'string'}
}
};
So in the model, the default schema is test1. If I visit the route /test1 in my browser then it will insert the data to the database in the schema test1, great.
Now, if I visit the route /test2 I am expecting the models meta schemaName to be set to test2 so that when the record is inserted it is inserted to the schema test2 in the database. This does not happen, it just inserts the value to the schema test1 as with the previous test.
So then I thought maybe I could set this via sails.config.models however this meta value is not an option there.
Does anyone know how I could achieve this end result?
Any responses would be greatly appreciated, thanks.

Sails.js add attribute from another table to a model

I am trying to pull an extra attribute for a model from a different table.
I have been trying with associations but it seems wrong to create an extra model and associate that to my original model.
This is my model Company.js
module.exports = {
schema: true,
autoCreatedAt: false,
autoUpdatedAt: false,
autoPK: false,
attributes: {
name: {
type: 'string'
},
url: {
type: 'string'
},
summary: {
type: 'text'
}
}
};
I have another table in MySQL with two columns, crunchbase_url and company_id, I would like to pull the crunchbase_url into the Company model, what would be the best way to do it without migrating the DB (not an option unfortunately).
Thanks,
Well, turns out that the documentation is fine and all works like a charm by simply creating another model and using one to many association with joined with via.
However, there is a bug that threw me off:
When defaultLimit is set to -1, the find action return an empty list if there are associations.