Definindo Modelos com Sequelize no Node.js
Um componente chave ao trabalhar com o Sequelize e bancos de dados são os modelos. Eles descrevem a estrutura dos dados armazenados no banco de dados e são o principal meio de interação com o banco.
Existem duas maneiras de definir modelos. A primeira envolve o uso do método define(). Por exemplo, podemos definir o modelo User, que representa um usuário:
const User = sequelize.define("user", {
  id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    primaryKey: true,
    allowNull: false,
  },
  name: {
    type: Sequelize.STRING,
    allowNull: false,
  },
  age: {
    type: Sequelize.INTEGER,
    allowNull: false,
  },
});O primeiro parâmetro do método é o nome do modelo. Nesse caso, o modelo é chamado "user". É importante observar que, se não existir uma tabela correspondente a esse modelo no banco de dados, ela será criada automaticamente. O nome da tabela será o nome do modelo no plural, conforme as regras da língua inglesa. Portanto, neste exemplo, a tabela será chamada "users". Isso deve ser considerado ao nomear os modelos.
O segundo parâmetro do método define() representa a estrutura do modelo, descrevendo seus campos. Para cada campo, são especificados vários atributos. O atributo type indica o tipo de dado do campo. Neste exemplo, os campos id e age são do tipo INTEGER, que representa um número inteiro, enquanto o campo name é do tipo STRING, que representa uma cadeia de caracteres.
Mapeamento de alguns tipos do Sequelize para tipos SQL:
| Sequelize | SQL | 
|---|---|
| Sequelize.STRING | VARCHAR(255) | 
| Sequelize.STRING.BINARY | VARCHAR BINARY | 
| Sequelize.TEXT | TEXT | 
| Sequelize.INTEGER | INTEGER | 
| Sequelize.FLOAT | FLOAT | 
| Sequelize.DOUBLE | DOUBLE | 
| Sequelize.DECIMAL | DECIMAL | 
| Sequelize.BOOLEAN | TINYINT(1) | 
O conjunto completo de tipos e seu mapeamento para tipos SQL pode ser consultado na documentação oficial.
Além disso, para cada campo, é possível definir mais atributos. O atributo allowNull indica se o campo pode ou não aceitar valores nulos. Por padrão, seu valor é true, ou seja, o campo pode não ter valor. Definir como false indica que o campo deve obrigatoriamente ter um valor.
Para o campo id, também foram definidos mais dois atributos. O atributo autoIncrement: true indica que o valor do campo será auto-incrementado, enquanto primaryKey: true define que o campo será a chave primária da tabela.
Segunda maneira de definir um modelo:
class User extends Model {}
User.init(
  {
    id: {
      type: Sequelize.INTEGER,
      autoIncrement: true,
      primaryKey: true,
      allowNull: false,
    },
    name: {
      type: Sequelize.STRING,
      allowNull: false,
    },
    age: {
      type: Sequelize.INTEGER,
      allowNull: false,
    },
  },
  {
    sequelize,
    modelName: "user",
  }
);Sincronizando com o banco de dados
Antes de interagir com o banco de dados, é necessário garantir que as tabelas estão de acordo com a definição dos nossos modelos. Para sincronizar, usamos o método sync:
sequelize
  .sync()
  .then((result) => {
    console.log(result);
  })
  .catch((err) => console.log(err));O método sync() alinha a estrutura do banco de dados com a definição dos modelos. Por exemplo, se uma tabela correspondente a um modelo estiver ausente no banco de dados, ela será criada.
Código completo da aplicaçãoÇ
const Sequelize = require("sequelize");
const sequelize = new Sequelize({
  dialect: "sqlite",
  storage: "programicio.db",
});
const User = sequelize.define("user", {
  id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    primaryKey: true,
    allowNull: false,
  },
  name: {
    type: Sequelize.STRING,
    allowNull: false,
  },
  age: {
    type: Sequelize.INTEGER,
    allowNull: false,
  },
});
sequelize
  .sync()
  .then((result) => {
    console.log(result);
  })
  .catch((err) => console.log(err));É importante notar que, além dos campos definidos no modelo, dois campos adicionais serão criados na tabela por padrão: createdAt e updatedAts. Eles são do tipo datetime e registram, respectivamente, o momento da criação e da última atualização de cada linha na tabela.
Por exemplo, ao trabalhar com um banco de dados SQLite, a tabela criada será descrita pelo seguinte script:
CREATE TABLE IF NOT EXISTS `users` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` VARCHAR(255) NOT NULL,
`age` INTEGER NOT NULL,
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL
);Além disso, não é necessário definir o campo id no modelo, pois o Sequelize criará esse campo automaticamente como chave primária.
Também é possível criar a tabela manualmente no servidor e depois conectá-la ao modelo sem a necessidade de sincronização.
Se esses campos adicionais createdAt e updatedAt não forem necessários, é possível desativá-los ao definir o objeto Sequelize usando o parâmetro define: {timestamps: false}:
const Sequelize = require("sequelize");
const sequelize = new Sequelize({
  dialect: "sqlite",
  storage: "programicio.db",
  define: {
    timestamps: false,
  },
});
const User = sequelize.define("user", {
  id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    primaryKey: true,
    allowNull: false,
  },
  name: {
    type: Sequelize.STRING,
    allowNull: false,
  },
  age: {
    type: Sequelize.INTEGER,
    allowNull: false,
  },
});
sequelize
  .sync()
  .then((result) => console.log(result))
  .catch((err) => console.log(err));Se já existir uma tabela no banco de dados que não corresponde à definição do modelo, podemos usar o parâmetro {force: true} para excluir a tabela existente e criar uma nova com a estrutura correta:
sequelize
  .sync({ force: true })
  .then((result) => {
    console.log(result);
  })
  .catch((err) => console.log(err));