Sequelize .create is not generating content for my model - node.js

I looked for this question everywhere but, I haven't found it.
I'm using Sequelize for Postgres, and I'm trying to add content to a model. It's not throwing any errors, except just a warning that says that string based operations have been deprecated, but this isn't an operation.
sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators
Here's my model and .create code
const Sequelize = require('sequelize');
const sequelizeInstance = new Sequelize('journal_entries', 'KupidoExportLLC',
{
dialect: 'postgres'
});
module.exports = function(sequelizeInstance, DataTypes){
const Entries = sequelizeInstance.define('entries', {
user: Sequelize.STRING,
title: Sequelize.STRING,
content: Sequelize.TEXT
})
Entries.sync().then(function(){
Entries.create({
user: 'I need to get this to work',
title: 'Ill be really happy when this does work',
content: 'It will work this time'
})
});
return Entries;
}
Here's what my commandline is showing
sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules/sequelize/lib/sequelize.js:242:13
When I go look at my table, it's empty
journal_entries=# SELECT * FROM entries;
id | user | title | content | createdAt | updatedAt
----+------+-------+---------+-----------+-----------
(0 rows)
I have no idea what else it could be

You need to turn off the warnings.
In your config.JSON file or (If you have initialize the connection in the same file)
Turn the warning off, as given:
IN Config.JSON
{
"development": {
"username": "root",
"password": "12345",
"database": "fasttrack",
"host": "localhost",
"dialect": "mysql",
"define": {
"timestamps": false
},
"operatorsAliases": false
},
"test": {
"username": "root",
"password": "12345",
"database": "fasttrack",
"host": "localhost",
"dialect": "mysql",
"define": {
"timestamps": false
},
"operatorsAliases": false
},
"production": {
"username": "root",
"password": "12345",
"database": "fasttrack",
"host": "localhost",
"dialect": "mysql",
"define": {
"timestamps": false
},
"operatorsAliases": false
}
}
Inline declaration of connection
const sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: config.dialect,
pool: {
max: 5,
min: 0,
idle: 10000
},
logging: false,
freezeTableName: true,
operatorsAliases: false
});

you are working with Promises here, you have either to await or return them.
if you have async await available in your node version you could just do:
module.exports = async function(sequelizeInstance, DataTypes){
const Entries = sequelizeInstance.define('entries', {
user: Sequelize.STRING,
title: Sequelize.STRING,
content: Sequelize.TEXT
});
await sequelizeInstance.sync();
await Entries.create({
user: 'I need to get this to work',
title: 'Ill be really happy when this does work',
content: 'It will work this time'
});
const entries = await Entries.findAll();
console.log(entries.map(e => e.get({ plain: true })));
return Entries;
};
or if not
module.exports = async function(sequelizeInstance, DataTypes){
const Entries = sequelizeInstance.define('entries', {
user: Sequelize.STRING,
title: Sequelize.STRING,
content: Sequelize.TEXT
});
return sequelizeInstance.sync().then(() => {
return Entries.create({
user: 'I need to get this to work',
title: 'Ill be really happy when this does work',
content: 'It will work this time'
});
})
.then(() => {
return Entries.findAll().then(entries => {
console.log(entries.map(e => e.get({ plain: true })));
return entries;
})
});
};

Related

Migrations with Separate Entity Definition

I am trying to update my database using the entities with separate entity definition.
The database isn't updated either with the option synchronize = true or with the command:
ts-node ./node_modules/typeorm/cli.js migration:generate -n CreateDatabase
which generates an empty migration file.
What am I forgetting?
Steps to reproduce or a small repository showing the problem:
ormconfig.json
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "postgres",
"password": "secret",
"database": "app",
"entities": ["src/**/entities/*.entity.ts"],
"migrations": ["src/database/migrations/*.ts"],
"cli": {
"migrationsDir": "src/database/migrations"
},
"synchronize": true
}
topic.entity.ts
export class Topic {
title: string
}
topic.schema.ts
import { EntitySchema, EntitySchemaColumnOptions } from 'typeorm'
import { Topic} from '../topic.entity'
export const TopicSchema = new EntitySchema<Topic>({
name: 'topics',
target: Topic,
columns: {
title: {
name: 'title',
type: 'text',
nullable: true,
} as EntitySchemaColumnOptions,
},
})
Try split the topic.entity.ts to topic.entity.ts and topic.schema.ts and use only the topic.schema.ts on your ormconfig.json.
Change the entities section from your ormconfig.json to:
"entities": ["src/**/entities/*.schema.ts"]
I was struggling with this. What I did was to split into
Model and Schema. Model is a common Class.
Session.ts
export class Session {
token: string;
userId: string;
}
Session.entity.ts
And Schema. If you forget target it unifies every entity into one table. Don't forget that. And use the same name as model so it matches properly.
import {EntitySchema} from "typeorm";
import { Session } from "../models/Session";
export const SessionEntity = new EntitySchema<Session>({
name: "Session", // BE CAREFUL: must be the same name as Model, STRING
target: Session, // This must be the Class itself, NOT STRING
columns: {
token: {
type: String,
primary: true,
generated: "uuid"
},
userId: {
type: String
}
}
});
And to use it
import { SessionEntity } from "../entities/Session.entity";
const connection = this.typeORMService.get("default");
const repository = this.ormService.connection.getRepository(SessionEntity);
const session = await repository.save({userId: "123"});
Another issue that you may have is that if you add your settings in the code and in ormconfig.json it will use the code settings. So be careful with that as well.
I prefer to setup settings in code like this:
const rootDir = __dirname;
#Configuration({
rootDir,
typeorm: [
{
name: "default",
synchronize: true,
type: "postgres",
url: process.env.DATABASE_URL || config.DATABASE_URL,
ssl: process.env.DATABASE_URL ? true : false, // If env var is not set then it is dev
"entities": [
`${rootDir}/**/*.entity.js`,
`${rootDir}/**/*.entity.{ts,js}`
],
"migrations": [`${rootDir}/migrations/**/*.js`],
subscribers: [
`${rootDir}/subscriber/*.js}`
]
}
]
})
I hope you find this useful. If you have any doubts please let me know.

Change column name Sequilize

I want to change default column name in my final output which comes from Mysql database when i am accessing database using NodeJS and Sequelize connection.
I am connecting using following code:-
import Sequelize from "sequelize";
let dbConnection = new Sequelize('DB', 'abc', 'password', {
host: '127.0.0.1',
port: 4242,
dialect: 'mysql',
dialectOptions: {
requestTimeout: 0,
},
});
const Listing = dbConnection.define('TableName', {
tour_title: {
type: Sequelize.STRING,
}
}, { freezeTableName: true, timestamps: false });
For example, I want to change tour_title by tour_name in the above column only in the final sequelize output. I do not want any change in database column names.
To change column name only in final output
TableName.findAll({
attributes: ['id', ['tour_title', 'tour_name']] /
})
.then((data) => {
console.log(data);
});
To change column name in database
This may help you, follow this steps
Step 1: npm install -g sequelize-cli
To install sequelize command line tool
Step 2: sequelize migration:create --name rename-column-tour_title-to-tour_name-in-tabelname
Step 3: Open newly created migration file and add below code
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.renameColumn('tableName', 'tour_title', 'tour_name');
},
down: (queryInterface, Sequelize) => {
return queryInterface.renameColumn('tableName', 'tour_name', 'tour_title');
}
};
Step 4: in command line run this below command
sequelize db:migrate
Now your column name changed successfully.
If you want an alias for a column name in the ouput , you can do something like this:
TableName.findAll({
attributes: ['id', ['tour_title', 'tour_name']] //id, tour_title AS tour_name
})
.then(function(data) {
res.json(data);
});
Whenever you fetch any records you can write the column name in a cascaded list and make an alias.
Check for the documentation here : http://docs.sequelizejs.com/manual/tutorial/querying.html
The above answers only works for the query results. If you want to keep your underscore name convention on the database and use for example camelCase for your javascript environment you need to do this:
const ChildTable = dbConnection.define('ChildTable', { //this table name is how you call it on sequelize
tourTitle: { //this is the name that you will use on javascript
field: 'tour_title', // this will be the name that you fetch on your db
type: Sequelize.STRING,
},
parentTableId: { // You need to define the field on the model, otherwise on sequelize you'll have to use the db name of the field
field: 'parent_table_id', //this is defined above on the association part
type: Sequelize.INTEGER,
}
}, { freezeTableName: true, timestamps: false, tableName: 'TableName', //this is the real name of the table on the db
underscored: true, });
ChildTable.associate = (models) => {
ChildTable.belongsTo(models.ParentTable, { as: 'ParentTable', foreignKey: 'parent_table_id', onDelete: 'cascade' });
};
This way you have an "alias" for your fields on all the Sequelize / javascript environment and you keep your names on the db. See also that you have to do the same with the foreign keys on associations, otherwise you'll have to use the original name.
I'd add something to #Deepak's answer. When I tried it the Step 4: (I am a newbie), it prompted that
"Cannot find config.json Have you run sequelize init? "
Then I executed that init command then it made a config.json file inside the config folder. So the file contained below objects.
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
Then I executed the sequelize db:migrate. It prompted another error as
Sequelize CLI [Node: 18.7.0, CLI: 6.4.1, ORM: 6.21.4]
Loaded configuration file "config\config.json".
Using environment "development".
ERROR: Access denied for user 'root'#'localhost' (using password: NO)
Then what I did was I changed the config.json file to something like this -->
{
"development": {
"username": "root",
"password": "<this should include your root password>",
"database": "<this should include your db>",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
And then migration was done successfully!

sequelize.js association accessor

I made API server with Node.js
Also I use sequelize.js(version 4) for communicate with MySQL.
My table structure is here.
[Article]
no(PK)
subject
content
created_at
updated_at
[Comment]
no(PK)
content
created_at
updated_at
article_no(FK to Article)
[index.controller.js]
import { Article, Comment } from '../model/model';
export const index = (req, res) => {
res.send('controller index');
};
export const getArticle = (req, res) => {
try {
Article.all()
.then(article => {
res.status(200).json({status: true, result: article});
});
} catch(e) {
res.status(500).json({status: false, result: "get article fail"});
}
}
export const addArticle = (req, res) => {
const { subject, content } = req.body;
try {
Article.create({
subject: subject,
content: content
})
res.status(200).json({status: true, result: "article write success"});
} catch(e) {
res.status(500).json({status: false, result: "article fail"});
}
}
export const getComment = (req, res) => {
try {
Comment.all()
.then(comment => {
res.status(200).json({status: true, result: comment})
});
} catch(e) {
res.status(500).json({status: false, result: "get comment fail"});
}
}
export const addComment = (req, res) => {
const { content, article_no } = req.body;
try {
Comment.create({
content: content,
article_no: article_no
})
.then(() => res.status(200).json({status: true, result: "comment write success"}))
} catch(e) {
console.log(e);
res.status(500).json({status: false, result: "comment fail"});
}
}
[index.js]
import express from 'express';
import { index, getArticle, getComment,addArticle, addComment } from './index.controller';
const router = express.Router();
router.get('/', index);
router.get('/article', getArticle);
router.post('/article', addArticle);
router.get('/comment', getComment);
router.post('/comment', addComment);
export default router;
[model.js]
import Sequelize from 'sequelize';
const sequelize = new Sequelize('db', 'id', 'pw', {
host: '127.0.0.1',
dialect: 'mysql'
})
export const Article = sequelize.define('article', {
no: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
subject: {
type: Sequelize.STRING,
allowNull: false
},
content: {
type: Sequelize.STRING,
allowNull: false
}
}, {
freezeTableName: true,
underscored: true
})
export const Comment = sequelize.define('comment', {
no: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
content: {
type: Sequelize.STRING,
allowNull: false
}
}, {
freezeTableName: true,
underscored: true
})
Article.hasMany(Comment, {as: 'Comments'}); // association
Comment.belongsTo(Article); // association
sequelize.sync({
force: false
});
Because of association(hasMany, belongsTo), article_no column will be added to Comment table.
Refer to this document, http://docs.sequelizejs.com/manual/tutorial/associations.html#one-to-many-associations-hasmany-
It says that Instances of Project will get the accessors getWorkers and setWorkers.
In my case, it will be getComments and setComments.
But I don't know exactly how can I get all the comments related articles with using accessor.
Current output is here. (If I connect to GET /article)
{
"status":true,
"result":[
{
"no":1,
"content":"comment test",
"created_at":"2018-07-18T05:00:45.000Z",
"updated_at":"2018-07-18T05:00:45.000Z",
"article_no":1
}
]
}
Desired output is here
{
"status":true,
"result":[
{
"no":1,
"content":"comment test",
"created_at":"2018-07-18T05:00:45.000Z",
"updated_at":"2018-07-18T05:00:45.000Z",
"article_no":1,
"comments": [
// related comments here!
]
}
]
}
Thanks.
When you want to join another model you should use include in your query
User.findAll({
include: [
{ model: Profile, required: true // inner join }
],
limit: 3
});
Check out the Sequelize model usage docs.
To access the comments with accessors you will need do something like this:
const articles = await Article.all();
articles.forEach(article => {
const comments = await article.getComments();
})
The idea behind is that each article sequelize object will have the accessor getComments but internally what it does when you execute getComments it makes a new request to the database with the prepopulated articleId in the comments where query. This is called lazy loading because you can load the data when you need it. But that is not your case.
For the desired output I suggest to use the include method cause it will make a single request to the database.

sequelize seed unable to insert the data in SQLite

I am trying to insert the dummy data using sequelize-cli command
sequelize db:seed --seed seeders/20170212081140-subject_tags.js
here is my config file
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "sqlite",
"seederStorage": "sequelize",
"storage": "./test"
}
}
and here my seeder file
use strict';
module.exports = {
up: function(queryInterface, Sequelize) {
return
queryInterface.bulkUpdate('subject_tags', [
{
tag: 'agricultural-sciences',
tag_description: '',
subject_category: 'biological_&_medical_sciences',
createdAt: new Date(),
updatedAt: new Date()
}, {
tag: 'biochemistry',
tag_description: '',
subject_category: 'biological_&_medical_sciences',
createdAt: new Date(),
updatedAt: new Date()
}, {
tag: 'bioinformatics',
tag_description: '',
subject_category: 'biological_&_medical_sciences',
createdAt: new Date(),
updatedAt: new Date()
}
] , {});
},
down: function(queryInterface, Sequelize) {
return
queryInterface.bulkDelete('subject_tags', null, {});
}
};
Though I am getting the status
Using environment "development".
== 20170212081140-subject_tags: migrating =======
== 20170212081140-subject_tags: migrated (0.053s)
I tried bulkCreate and bulkInsert in the seed file , all of them run successful, but data does not get inserted into the table
the data does not get inserted. Is I am doing something wrong?
It seems to be issue with sequlizer, after return statement it unable to handle space with newline character
module.exports = {
up: function(queryInterface, Sequelize) {
//old code
//return
// queryInterface.bulkUpdate('subject_tags', [
//new code
return queryInterface.bulkUpdate('subject_tags', [
//.........
Javascript will automatically add a semi-colon after a dangling return statement.
It doesn't reach the bulkUpdate code.

How to insert initial data using sequelize migrations/seeds?

I'm trying to create my initial migration to populate the test database but I can't get it working. This is what I have in my migration:
'use strict';
module.exports = {
up: function (queryInterface, Sequelize) {
return [
queryInterface.bulkInsert('Users', [
{ username: "user1" },
{ username: "user2" }
])];
},
down: function (queryInterface, Sequelize) {
return queryInterface.dropTable('Users');
}
};
And I get this error:
== 20151024144833-create-conjugation: migrating =======
{ [SequelizeUniqueConstraintError: Validation error]
name: 'SequelizeUniqueConstraintError',
message: 'Validation error',
errors: [],
fields: [] }
There must be an easier way to do this. I've checked other SO questions, but the syntax has changed in the current version of sequelize.
UPDATE
Ok, I realized my mistake: I was assuming that sequelize would take care of the timestamps. This fixes the problem:
up: function (queryInterface, Sequelize) {
console.log(User);
return [
queryInterface.bulkInsert('Users', [
{ username: "user1", createdAt: Date.now(), updatedAt: Date.now() },
{ username: "user2", createdAt: Date.now(), updatedAt: Date.now() }
])
];
}
But I'm still wondering if this is the right way to seed my database. Is there a way to do it using User.create({})?
new Date()
also required for mysql, i.e.
return queryInterface.bulkInsert('users', [
{
"Forename":"A",
"Surname": "User",
"UserType":"1",
"Email":"auser#gmail.com",
"Password":"password",
"LastLogin":0,
"Tokens": JSON.stringify({"tokens":[]}),
"CreatedBy": 999,
"CreatedAt": new Date(),
"UpdatedAt": new Date()
}]);
You can use next:
const City = sequelize.define('city', {
name: { type: Sequelize.STRING },
order_: { type: Sequelize.INTEGER }
});
City.sync().then(() => {
City.create({
name: 'Neuquen',
order_: 0
});
City.create({
name: 'General Roca',
order_: 1
});
});
Or read about "migrations" at http://docs.sequelizejs.com/en/latest/docs/migrations/
An alternative could be use : sequelize fixtures , you could init your tables with default data declared as a json file or other format.
For a quick and easy way (without seeds or migrations) on sequelize v6:
I modified my sequelize.sync() call:
import { Sequelize } from 'sequelize';
// This will create an in-memory sqlite db
const sequelize = new Sequelize('sqlite::memory:', {
logging: sequelizeLogger
});
await sequelize
.sync({ force: true })
.then(() => {
// seed db
Users.create({ username: 'user1' })
});

Resources