Can Sequelize use something like a getter or setter in a find query?

Viewed 171

For my email field, I store and query emails as lowercase strings to avoid duplicate emails like user@example.com and User@example.com. I have a set method defined in my model like:

const User = sequelize.define('user', {
  email: {
    type: DataTypes.STRING,
    unique: { msg: 'That email is already registered.' },
    validate: { isEmail: { msg: 'Invalid email.' } },
    set(value) {
      this.setDataValue('email', value.toLowerCase().trim())
    }
  }
})

This prevents setting emails with uppercase letters, but it does not prevent queries with uppercase letters. To avoid queries, I have to remember to use .toLowerCase() everywhere. It would be better if I could define it on the model so that a query like this would just work:

const user = await User.findOne({ where: { email: 'SomeEmail@example.com' } })
1 Answers

You can use the hooks in models to store the email in lower case. Please have a look in below example

const createUserModel = (sequelize, { STRING, UUIDV4, UUID, DATE }) => {
  const User = sequelize.define(
    'User',
    {
      userId: {
        type: UUID,
        defaultValue: UUIDV4,
        primaryKey: true,
      },
      email: {
        type: STRING,
        allowNull: false,
        unique: true,
        validate: {
          isEmail: true,
        },
      },
      password: {
        type: STRING,
        allowNull: true,
      },
    },
    {
      freezeTableName: true,
      timestamps: false,
      hooks: {
        beforeCreate: async instance => {
          const email = instance.get('email');
          instance.set('email', email.toLowerCase());
        },
        beforeUpdate: async instance => {
          if (instance.changed('email')) {
            const email = instance.get('email');
            instance.set('email', email.toLowerCase());
          }
        },
      },
    },
  );

  return User;
};

module.exports = {
  createUserModel,
};
Related