Search code examples
node.jssequelize.js

Why does Sequelize pluralize / singularize names of anything all? And how to stop that completely?


The names of my tables in the .create() method function and model definitions are swinging from singular to plural and vice-versa. Why does Sequelize have this functionality at all? And why is disabling it so unstable?

The table names in my database are (as in the code) "user", "email", "settings". But when doing the INSERT and SELECT SQL statements Sequelize singularizes the names as if I there was need for a library to choose the best name for my database tables! Because of that, some INSERTs fail.

Here is my code:

// DEPENDENCIES
const Sequelize = require('sequelize');



// Connection set up:
const sequelize = new Sequelize(
    'sql_database_1',
    'sqlusername1',
    'dbpassw0rd',
    { // Sequelize options:
        host: 'localhost',
        port: 3306,
        dialect: 'mysql',
        operatorsAliases: false,
        pool: {
            max: 5,
            min: 0,
            acquire: 30000,
            idle: 10000
        },
        logging: console.log,
        define: {
            freezeTableName: true, // Do not change my table names.
            timestamps: false // I will do this individually, thanks.
        },
    });



// Set up models:
const User = sequelize.define('user',
    { // Database columns:
        user_id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        column1: Sequelize.STRING,
    });

const Settings = sequelize.define('settings',
    { // Database columns:
        entry_id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        owner_id: Sequelize.INTEGER,
        column1: Sequelize.STRING
    });

const Email = sequelize.define('email',
    { // Database columns:
        entry_id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        owner_id: Sequelize.INTEGER,
        column1: Sequelize.STRING
    });



// Set up associations:
User.hasOne(Settings,
    { // Options:
        foreignKey: 'owner_id'
    });

User.hasMany(Email,
    { // Options:
        foreignKey: 'owner_id'
    });



// Actions:
sequelize
    .sync({
        force: true
    })
    .then(function() {
        User
            .create({
                    column1: 'test123',
                    settings: { // STACK OVERFLOW: Not working because of Sequelize singularizing the name.
                        column1: 'This is dummy address'
                    },
                    emails: [ // STACK OVERFLOW: I need to write this table name in plural to work because Sequelize is changing MY names...
                        { column1: 'Some data here' },
                        { column1: 'Other data there' }
                    ],
                },
                {
                    include: [Settings, Email]
                })
    })
    .then(function() {
        User
            .findOne({
                include: [Settings, Email],
            })
            .then(function(result) {
                console.log('FindAll results:\n', JSON.stringify(result));
            });
    });

As you can see, I am using "define: { freezeTableName: true }" in the object dedicated to set up Sequelize options. It is only working when creating the new table names: it does not pluralize them. The INSERT and SELECT statements still have a similar same problem: they are being singularized.

Can this be a bug?


Solution

  • It has to do with the association you define. For settings, we have the hasOne relationship; hence, the name is singular. For emails, we have the hasMany relationshop; hence, the name is plural.

    Let's look at an example below.

    const User = sequelize.define('user', {
      username: Sequelize.STRING,
    });
    
    const Email = sequelize.define('emails', {
      text: Sequelize.STRING,
    });
    
    User.hasMany(Email);
    
    sequelize.sync({ force: true })
      .then(() => User.create({
        username: 'test1234',
        emails: {
          text: 'this is dummy Email123'
        },
      }, { include: [Email] }))
      .then(user => {
        console.log(user.dataValues);
      });
    

    I have used emails because User has the hasMany relationship with Email. If I change the relationship type to hasOne, I will use the singular name.

    const User = sequelize.define('user', {
      username: Sequelize.STRING,
    });
    
    const Email = sequelize.define('emails', {
      text: Sequelize.STRING,
    });
    
    
    User.hasOne(Email);
    
    sequelize.sync({ force: true })
      .then(() => User.create({
        username: 'test1234',
        email: {
          text: 'this is dummy Email123'
        },
      }, { include: [Email] }))
      .then(user => {
        console.log(user.dataValues);
      });