sequelize for Node.js : ER_NO_SUCH_TABLE - node.js

I'm new to sequelize and Node.js.
I coded for test sequelize, but error occured "ER_NO_SUCH_TABLE : Table 'db.node_tests' doesn't exist"
Error is very simple.
However, I want to get data from "node_test" table.
I think sequelize appends 's' character.
There is my source code.
var Sequelize = require('sequelize');
var sequelize = new Sequelize('db', 'user', 'pass');
var nodeTest = sequelize.define('node_test',
{ uid: Sequelize.INTEGER
, val: Sequelize.STRING} );
nodeTest.find({where:{uid:'1'}})
.success(function(tbl){
console.log(tbl);
});
I already create table "node_test", and inserted data using mysql client.
Does I misunderstood usage?

I found the answer my own question.
I appended Sequelize method option following. {define:{freezeTableName:true}}
Then sequelize not appends 's' character after table name.

Though the answer works nicely, I nowadays recommend the use of the tableName option when declaring the model:
sequelize.define('node_test', {
uid: Sequelize.INTEGER,
val: Sequelize.STRING
}, {
tableName: 'node_test'
});
http://docs.sequelizejs.com/manual/tutorial/models-definition.html

Sequelize is using by default the plural of the passed model name. So it will look for the table "node_tests" or "NodeTests". Also it can create the table for you if you want that.
nodeTest.sync().success(function() {
// here comes your find command.
})
Sync will try to create the table if it does not already exist. You can also drop the existing table and create a new one from scratch by using sync({ force: true }). Check the SQL commands on your command line for more details about what is going on.

When you define a model to an existing table, you need to set two options for sequelize to:
find your table name as-is and
not fret about sequelize's default columns updatedAt and createdAt that it expects.
Simply add both options like so:
var nodeTest = sequelize.define('node_test',
{ uid: Sequelize.INTEGER , val: Sequelize.STRING},
{ freezeTableName: true , timestamps: false} //add both options here
);
Note the options parameter:
sequelize.define('name_of_your_table',
{attributes_of_your_table_columns},
{options}
);
Missing either options triggers respective errors when using sequelize methods such as nodeTest.findAll().
> ER_NO_SUCH_TABLE //freezeTableName
> ER_BAD_FIELD_ERROR //timestamps
Alternatively, you can:
create a fresh table through sequelize. It will append "s" to the table name and create two timestamp columns as defaults or
use sequelize-auto, an awesome npm package to generate sequelize models from your existing database programmatically.
Here's the sequelize documentation for option configurations.

In my case, it was due to case. I was having:
sequelize.define('User', {
The correct way is to use lowercase:
sequelize.define('user', {

Related

Add lower() to a field in addIndex() in sequelize migration

To create a unique index in sequelize migrations we can do something like below,
await queryInterface.addIndex(SCHOOL_TABLE, {
fields: ['name', 'school_id'],
unique: true,
name: SCHOOL_NAME_ID_UNIQUE_INDEX,
where: {
is_deleted: false
},
transaction,
})
The problem is It allows duplicates due to case senstivity.
In the doc here, It is mentioned that fields should be an array of attributes.
How can I apply lower() to name field so that It can become case insensitive?
I am using a workaround for now, using raw query. I don't think addIndex() supports using functions on fields.
await queryInterface.sequelize.query(`CREATE UNIQUE INDEX IF NOT EXISTS ${SCHOOL_NAME_ID_UNIQUE_INDEX}
ON ${SCHEMA}.schools USING btree (lower(name), school_id) where is_deleted = false;
`, { transaction});

Sequelize Error : Column names in each table must be unique

I had an error in Sequelize with a foreign key not matching a column name. Checking the db, I saw that the column 'WokflowId' was named 'WorkflowID', so I changed the name in the Sequelize model.
It look like this
'use strict';
const Sequelize = require('sequelize');
const sequelize = require('../util/database');
const WorkflowsAccessRights = sequelize.define('Workflows_AccessRights', {
id:{
type: Sequelize.BIGINT,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
WorkflowID: Sequelize.BIGINT,
GroupID: Sequelize.BIGINT,
Enabled: Sequelize.INTEGER
},{
timestamps: false,
freezeTableName: true,
});
module.exports = WorkflowsAccessRights
But now that I changed the column name to get the right one, I get this error
Column names in each table must be unique. Column name 'WorkflowId' in table 'Workflows_AccessRights' is specified more than once.
Except that no column has this name now... Did I miss something in the setup or is there a way to freeze the column name?
Hope the following link will be helpful for you. It asks to put IF NOT EXISTS to the SQL script as follows,
IF NOT EXISTS(SELECT * FROM sys.columns WHERE Name = 'ColumnName'
AND object_id = OBJECT_ID('YourTableName'))
BEGIN
ALTER TABLE dbo.YourTableName
ADD ColumnName INT -- or whatever it is
END
Check this link. It is the same question that you have asked
So, after searching in the whole project. I found out that I was calling a foreignKey on WorkflowId. Therefore Sequelize tried to create a new column called WorkfklowId and had a bug doing it. I just renamed the foreignKey and it worked.

One to many relation in Dynamodb Node js (Dynamoose)

I am using Dynamodb with nodejs for my reservation system. And Dynamoose as ORM. I have two tables i.e Table and Reservation. To create relation between them, I have added tableId attribute in Reservation which is of type Model type (of type Table type), as mentioned in the dyanmoose docs. Using the document.populate I am able to get the Table data through the tableId attribute from Reservation table. But how can I retrieve all Reservation for a Table? (Reservation and Table has one to many relation)?
These are my Model:
Table Model:
const tableSchema = new Schema ({
tableId: {
type: String,
required: true,
unique: true,
hashKey: true
},
name: {
type: String,
default: null
},
});
*Reservation Model:*
const reservationSchema = new Schema ({
id: {
type: Number,
required: true,
unique: true,
hashKey: true
},
tableId: table, \\as per doc attribute of Table (Model) type
date: {
type: String
}
});
This is how I retrieve table data from reservation model
reservationModel.scan().exec()
.then(posts => {
return posts.populate({
path: 'tableId',
model: 'Space'
});
})
.then(populatedPosts => {
console.log('pp',populatedPosts);
return {
allData: {
message: "Executedddd succesfully",
data: populatedPosts
}
}
})
Anyone please help to retrieve all Reservation data from Table??
As of v2.8.2, Dynamoose does not support this. Dynamoose is focused on one directional simple relationships. This is partly due to the fact that we discourage use of model.populate. It is important to note that model.populate does another completely separate request to DynamoDB. This increases the latency and decreases the performance of your application.
DynamoDB truly requires a shift in how you think about modeling your data compared to SQL. I recommend watching AWS re:Invent 2019: Data modeling with Amazon DynamoDB (CMY304) for a great explanation of how you can model your data in DynamoDB in a highly efficient manner.
At some point Dynamoose might add support for this, but it's really hard to say if we will.
If you truly want to do this, I'd recommend adding a global index to your tableId property in your reservation schema. Then you can run something like the following:
async function code(id) {
const reservation = await reservationModel.get(id);
const tables = await tableModel.query("tableId").eq(id).exec(); // This will be an array of `table` entries where `"tableId"=id`. Remember, it is required you add an index for this to work.
}
Remember, this will cause multiple calls to DynamoDB and isn't as efficient. I'd highly recommend watching the video I linked above to get more information about how to model your data in an more efficient manner.
Finally, I'd like to point out that your unique: true code does nothing. As seen in the Dynamoose Attribute Settings Documentation, unique is not a valid setting. In your case since you don't have a rangeKey, it's not possible for two items to have the same hashKey, so technically it's already a unique property based on that. However it is important to note that you can overwrite existing items when creating an item. You can set overwrite to false for document.save or Model.create to prevent that behavior and throw an error instead of overwriting your document.

Sequelize how not to redefine models every time server starts

In Sequelize tutorials, it is said that a single model is generated in this way:
const User = sequelize.define('user', {
firstName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
}
});
And than saved (i.e. create table) like this :
User.sync().then(() => {
// do whatever
});
But I expect to do that just once, I need to create tables just once. So the next time I run the script how to just retrieve models (i.e. tables) that were defined before with the above code.
in sync method you can pass an option to avoid sync of database tables every time. This option will make sure that your application checks for table in database, if it exist then it will not create otherwise it will create table.
User.sync(
{force: false}).then(() => {
// do whatever
});
Let me know if you still face issue. I am using sequalize and i am not getting this issue.

How to create a UNIQUE constraint on a JSONB field with Sequelize

I'm using the Sequelize ORM in NodeJS to manage a postgreSQL database.
I'm using the JSONB datatype in my table, I need an index on the JSONB field and an unique constraint on a property of this JSON.
If I have to do in a classic SQL here my script :
CREATE TABLE tableJson (id SERIAL PRIMARY KEY,
content JSONB NOT NULL);
CREATE INDEX j_idx ON tableJson USING gin(content jsonb_path_ops);
CREATE UNIQUE INDEX content_name_idx ON tableJson(((content->>'name')::varchar));
I've found how to create the table with the INDEX but not how to deal with the UNIQUE constraint. Here is a sample of my script :
var tableJson = sequelize.define('tableJson', {
content: Sequelize.JSONB
}, {
indexes: [{
fields: ['content'],
using: 'gin',
operator: 'jsonb_path_ops'
}
});
Is there a solution for my problem? If not I'll probably use the sequelize.query method to execute raw query but this is not very evolutive.
Any help would be appreciated!
This is the workaround I use to add indexes on JSONB fields with Postgres and Sequelize.
First, set the quoteIdentifiers option to false in your Sequelize client.
const seq = new Sequelize(db, user, pass, {
host: host,
dialect: 'postgres',
quoteIdentifiers: false,
});
(Watch out though, this will make all your table names case insensitive when created by Sequelize.sync())
You can now add indexes on JSONB fields this way in your model definition :
indexes: [
{
fields: ['content'],
using: 'gin',
operator: 'jsonb_path_ops'
},
{
fields: ['((content->>\'name\')::varchar)'],
unique: true,
name: 'content_name_idx',
}
],

Resources