Sequelize: how to let the database handle primary key value? - node.js

I'm using sequelize 6.5.0. I created a simple model to do two rudimentary things: a) find records, b) create records. I'm having trouble creating records; specifically, ones with primary key. If I designate the column as primaryKey like so:
const Table = sequelize.define('table', {
id: {
type: DataTypes.UUID,
primaryKey: true
},
datum: {...}
...
and try to create a record like so:
Table.create({datum: 'abc'})
then it will try (and fail) to set the primary key with:
INSERT INTO "table" ("id","datum") VALUES ($1,$2) RETURNING ...;
which is 50% what I did not ask it to do. Now, I don't need this to happen since default value for id is already handled at the database level. So, the next natural move was to not designate id as primaryKey:
const Table = sequelize.define('table', {
id: {
type: DataTypes.UUID,
// primaryKey: true
},
datum: {...}
...
But now sequelize attempts to get smart and throws a tantrum:
Uncaught Error: A column called 'id' was added to the attributes of 'table' but not marked with 'primaryKey: true'
Q) How do I get sequelize to NOT handle primary key on create?

I think you can skip the id field in the definition altogether, and PostgreSQL will still have one

Related

Sequlize generate a table with a foreign key while explicitly requested not to

I have the following association in PersonEntity:
#HasMany(() => SocialPostEntity, {
foreignKey: 'parentId',
foreignKeyConstraint: false,
})
posts?: SocialPostEntity[];
On the other hand the related column on SocialPostEntity:
#Column(DataType.INTEGER)
parentId: number;
The generated create table script has created the parentId column with a foreign key to PersonEntity. event though I have explicitly mentioned foreignKeyConstraint: false
Im not intended to use synchronize: true in production but I'm afraid that it means that my mapping is not accurate.
Bottom line I want parentId to be a simple integer, that's it.
Thanks

How to get sequelize getter to work with findAll

For sake of example, I have this very simple model:
const Blog = sequelize.define(
'Blog',
{
id: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
get() {
return this.getDataValue('id').toString();
}
},
},
)
I would like to return the id my records as strings, but it does not work:
const blogs = Blog.findAll({ raw: true })
console.log(blogs)
Returns a list of blogs with the id property as a number.
Any ideas why and if that's not the correct way to do this, what would it be?
If you want to use a different type for the primary key make sure to set autoIncrement: false. Typically you would use either a DataTypes.INTEGER or DataTypes.UUID as a primary key type but should work with a DataTypes.String as well. You will need to insert a unique value for each row.
If you want to run the getter you need to remove raw: true. When you specify raw results the columns that are returned from the database are mapped directly to a JSON object, in this case they are numeric. If you want to map the results back to a plain JSON object instead of Model Instances you can use Array.map() and Instance.toJSON().
Note that in your example you omitted await or thenable syntax as well which is necessary to get the results asynchronously.
const blogs = await Blog.findAll();
const plainObjs = blogs.map((blog) => blog.toJSON());

Customizing sequelize-cli generated IDs

Created a model using:
sequelize-cli model:create --name User --attributes "dispName:string,email:string,phoneNum1:string,vendorId:integer"
Which resulted in the following migration:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
dispName: {
type: Sequelize.STRING
},
// plus others...
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
I want to change the automatically defined ID to:
cognitoId: {
allowNull: false,
primaryKey: true,
type: Sequelize.STRING(100)
}
So:
Will sequelize be able to recognize this as the ID?
Where all do I need to make this change? I could only identify the migration file.
The model file doesn't have a definition for the cognitoId (or the original auto-generated id field): how will I be able to get the value of a User instance's cognitoId (in the data returned by queries)?
Will changing the auto-generated id field have repercussions down the line?
Is the field name id "magical"? I.e., does the primary key have to be named id?
Is there a better way to do this?
Will changing the types of the fields from Sequelize.STRING to Sequelize.STRING(100) create any issues down the line?
Why doesn't the models file generated by sequelize-cli have the id field defined?
When generating models+migrations from the command-line I couldn't find any syntax to specify the ID or any other customization for the fields.
Using:
[Node: 12.14.1, CLI: 5.5.1, ORM: 5.21.3]
PS: relatively new to NodeJS & completely new to Sequelize.
Yes
You should declare custom named PK in your model
see p.2. If you don't declare PK in your model then sequelize assumes you have id PK with an integer type, autoincremented. If you wish to assign your PK another name you should declare it in the model.
Depends on what changes you make
It is the default PK name in sequelize (see p.3). You can set different name to your PK manually declaring it in your model (see p.3)
Personally I prefer to declare all PKs in my models even if they have id name and default PK type and value.
No issues if all PK values do not exceed this length
see p.3
You can define names and types only for fields while generating models from the command line.

Difference between postgeSQL table contrains, sequelize options and sequelize validation?

Difference between postgeSQL table contrains, sequelize options and sequelize validation?
For example:
What is the difference between:
title: { type: Sequelize.STRING, allowNull: false},
and
title: { type: Sequelize.STRING, validate: { notNull: true }
and
CREATE TABLE mytable( username TEXT NOT NULL )
In the documentation they say:
// 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.
Why would the error be thrown from the db yet the constrain is in a sequelize model definition? Why not just throw it from sequelize? What is the purpose of the model definition then? Another thing that is confusing me is why we need extra validation from the 'validate option' yet we have constrains in the model as well.
Also what will happen if we put a constrain in the postgreSQL table and not in sequelize model or vice versa?
I suppose that allowNull: false directly translates to NOT NULL constraint when this ORM creates tables.
From https://sequelize.org/v5/manual/models-definition.html
// 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.
That is, first and third snippets are equivalent, provided that tables are created with ORM.
Validation in the second snippet happens on the "client" side (that is, when you run your JS code). If you have validation only, but not a constraint in the database then you can set NULL values e.g. by using some other client. If you have a database constraint then no matter what client do you use, you can't set NULL value.

MongoDB Ensure Index not stopping Duplicates

I am trying to stop duplicates in my Mongo DB Collection but they are still getting in. I am reading data from twitter and storing it like:
var data = {
user_name: response[i].user.screen_name,
profile_image: response[i].user.profile_image_url,
content: {
text: response[i].text
},
id: response[i].id_str,
};
and I have the following to stop any duplicates:
db[collection].ensureIndex( { id: 1, "content.text": 1 }, { unique: true, dropDups: true } );
The id field is working and no duplicates appear but "content.text" field does not work and duplicates are appearing. Any Ideas why?
When you enforce a unique constraint on a composite index, two documents are considered same only if the documents have the same value for both id and context.text fields and not for either key individually.
To enforce unique constraints on the fields, id and context.text individually, You could enforce it as below:
db.col.ensureIndex({"id":1},{unique:true}) and similarly for the other field.

Resources