sequlize方便操作数据库的工具

237 阅读9分钟

sequlize:方便操作数据库的工具

网站:入门 | Sequelize 中文文档 | Sequelize 中文网

1、Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server.

/** *

* 解释几个必要参数,以及日常使用频率较高的参数

* database:数据库的名称
* username:用来认证数据库连接的用户名
* password:用来认证数据库连接的密码
* host:数据库的host地址
* port:数据库服务的端口
* dialect:数据库语言,可以选mysql、postgres、sqlite等
* timezone:时区,将数据库时间转换成js的date时候会用到,默认是:‘+00:00’,我们一般设置成中国的时区,避免一些时间转换的麻烦
* logging:执行每次数据库操作,是否在在控制台输出原生sql的log
* pool:数据库连接池的设置,用的是默认配置
* freezeTableName:默认为false,是否需要固定表名,如果设置为true,js中定义表名会和数据库中创建的表名相同,如果为false,* * * Sequelize会按照他的规则生成一个表名
* timestamps:默认为true,默认情况下,Sequelize会为每个表创建2个字段,createdAt和updatedAt,设置为false则不会自动创建这2个字段
    • */

2、下载模块:cnpm i sequelize --save

3、下载mysql数据库的驱动程序:cnpm i mysql2 --save

4、新建文件夹sql,新建文件config.js:

module.exports = {
​
 sql: {
​
  database: "cake",
​
  username: "root",
​
  password: "123456",
​
  host: "localhost",
​
  port: "3306"
​
 }
​
}

5、在sql下再新建文件index.js:,链接数据库

const Sequelize = require('sequelize');
​
 //引入配置项const { sql } = require('./config')
​
 //配置数据库链接const seq = new Sequelize(sql.database, sql.username, sql.password, {   //数据库名,用户名,密码host: sql.host,    // 网络地址port: sql.port,    //端口号dialect: 'mysql',   //映射的数据库类型timezone: '+08:00',    //数据库时区  北京时间logging: false,    //设置数据库连接日志打印pool: {   //连接池
​
  max: 5,    //设置数据库链接最大5条
​
  min: 0,   //设置数据库链接最小0条
​
  idle: 10000     // 设置数据库链接超时时间 10s
​
 },
​
 define: {
​
  freezeTableName: true,     //禁止自动修改表名,默认为true
​
  timestamps: false,      //不需要添加 createdAt 和 updatedAt 两个时间戳字段,默认为true
​
 }
​
});
​
​
​
 // 连接数据库
​
seq.authenticate()
​
 .then(() => {
​
  console.log('========连接mysql数据库成功======');
​
 })
​
 .catch(err => {
​
  console.error('======连接数据库失败======', err);
​
 });
​
​
​
 //暴露出去module.exports = seq
​
​

6、新建文件夹model,新建文件shop.js,定义映射模型(映射数据库的表)

 //解构定义数据类型对象const { DataTypes } = require('sequelize');
​
 //引入数据库链接文件const  Seq = require('../sql')
​
​
​
 //  用户模型  --- 数据库中的shop表一一对应的映射关系const Shop = Seq.define("shop", {
​
 //定义表的键名
​
 id: {
​
  type: DataTypes.INTEGER,
​
   primaryKey: true,     // 是否为主键,要与数据库的表的主键对应,默认为false
​
   autoIncrement: true  ,     //是否自增,与数据库的表的主键对应,默认为false
​
 },
​
// uid: {
​
//  type: DataTypes.UUID,     //唯一id值
​
 // defaultValue: DataTypes.UUIDV4 // 或 DataTypes.UUIDV1  ,给一个默认的唯一id值
​
// },
​
 src: {
​
   type: DataTypes.STRING,  // 类型字母必须要全部大小
​
   allowNull: false     // 允许为空吗
​
 },
​
 url: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
  allowNull: false     // 允许为空吗
​
 },
​
 title: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
  allowNull: false     // 允许为空吗
​
 },
​
 content: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
 },
​
 tag: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
 },
​
 price: {
​
  type: DataTypes.INTEGER,  // 类型字母必须要全部大小
​
  allowNull: false     // 允许为空吗
​
 },
​
 weight: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
 },
​
 pound: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
 },
​
 count: {
​
  type: DataTypes.INTEGER,  // 类型字母必须要全部大小
​
  allowNull: false     // 允许为空吗
​
 },
​
 zone: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
 },
​
 type: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
 },
​
 isshow: {
​
  type: DataTypes.STRING,  // 类型字母必须要全部大小
​
  defaultValue: "true"
​
 }
​
}, {
​
 // 这是其他模型参数
​
  //  强制表名称等于模型名称
​
  freezeTableName: true,
​
})
​
​
​
 // 执行 数据库表的同步// ({ force: true })// force值为true时,表示每次执行这个方法都会先将表给删除 ,再重新创建
​
Shop.sync()
​
 .then(() => {
​
  console.log('=======shop表同步成功=======');
​
 })
​
 .catch(err => {
​
  console.error('=======shop表同步异常=======', err);
​
 });
​
 //暴露user表,在路由执行增加,删除,修改,查询
​
module.exports =  Shop ;

7、封装数据库的增删改查功能,创建server文件夹,index.js文件

/****

  • obj:查询条件数组,
  • setObj:更新对象,
  • update返回[更新条数],更新失败为[0]
  • find返回数据对象, 查询不到为[]
  • add返回插入的对象数据
  • del返回删除的数量,删除失败为 0

*/

//增加

const add = (model, obj) => {
  return new Promise((resolve, reject) => {
    model.create(obj)
      .then((data) => {
        resolve(data.dataValues)
      })
      .catch(err => {
        reject(err)
      })
  })
}

//查找数据

const find = (model, obj = {}) => {
  return new Promise((resolve, reject) => {
    model.findAll({
      where: obj
    })
      .then((data) => {
        resolve(data)
      })
      .catch(err => {
        reject(err)
      })
  })
}

// 更新数据

const update = (model, setObj, obj) => {
  return new Promise((resolve, reject) => {
    model.update(setObj, {
      where: obj
    })
      .then((data) => {
        resolve(data)
      })
      .catch(err => {
        reject(err)
      })
  })
}

//删除

const del = (model, obj) => {
  return new Promise((resolve, reject) => {
    model.destroy({
      where: obj
    })
      .then((data) => {
        resolve(data)
      })
      .catch(err => {
        reject(err)
      })
  })
}
​
### //暴露出去module.exports = {
  add, find, update, del
}
​
​

8、操作表数据的增删改查

8.1、插入数据

插入数据是通过模型对象的create方法实现的。例如,我们要向“users”表中插入一条记录,可以使用以下代码:
await User.create({
  username: 'test',
  password: '123456'
});

8.2、查询数据

查询数据是Sequelize中最常见的操作之一,Sequelize提供了多种查询方法,包括findAll(查询所有符合条件的记录)、findOne(查询符合条件的第一条记录)、findByPk(根据主键查询一条记录)等。例如,我们要查询“users”表中所有记录,可以使用以下代码:
const users = await User.findAll();
console.log(users);

8.3、更新数据

更新数据是通过模型对象的update方法实现的。例如,我们要将“users”表中username为“test”的记录的密码修改为“654321”,可以使用以下代码:
await User.update({ password: '654321' }, {
  where: {
    username: 'test'
  }
});

8.4、删除数据

删除数据是通过模型对象的destroy方法实现的。例如,我们要删除“users”表中username为“test”的记录,可以使用以下代码:
await User.destroy({
  where: {
    username: 'test'
  }
});

9、模型类型

字符串

DataTypes.STRING             // VARCHAR(255)
DataTypes.STRING(1234)       // VARCHAR(1234)
DataTypes.STRING.BINARY      // VARCHAR BINARY
DataTypes.TEXT               // TEXT
DataTypes.TEXT('tiny')       // TINYTEXT
DataTypes.CITEXT             // CITEXT          仅 PostgreSQL 和 SQLite.
DataTypes.TSVECTOR           // TSVECTOR        仅 PostgreSQL.

布尔

DataTypes.BOOLEAN            // TINYINT(1)

数字

DataTypes.INTEGER            // INTEGER
DataTypes.BIGINT             // BIGINT
DataTypes.BIGINT(11)         // BIGINT(11)
​
DataTypes.FLOAT              // FLOAT
DataTypes.FLOAT(11)          // FLOAT(11)
DataTypes.FLOAT(11, 10)      // FLOAT(11,10)
​
DataTypes.REAL               // REAL            仅 PostgreSQL.
DataTypes.REAL(11)           // REAL(11)        仅 PostgreSQL.
DataTypes.REAL(11, 12)       // REAL(11,12)     仅 PostgreSQL.
​
DataTypes.DOUBLE             // DOUBLE
DataTypes.DOUBLE(11)         // DOUBLE(11)
DataTypes.DOUBLE(11, 10)     // DOUBLE(11,10)
​
DataTypes.DECIMAL            // DECIMAL
DataTypes.DECIMAL(10, 2)     // DECIMAL(10,2)
无符号和零填充整数 - 仅限于MySQL/MariaDB

在 MySQL 和 MariaDB 中,可以将数据类型INTEGER, BIGINT, FLOATDOUBLE 设置为无符号或零填充(或两者),如下所示:

DataTypes.INTEGER.UNSIGNED
DataTypes.INTEGER.ZEROFILL
DataTypes.INTEGER.UNSIGNED.ZEROFILL
// 你还可以指定大小,即INTEGER(10)而不是简单的INTEGER
// 同样适用于 BIGINT, FLOAT 和 DOUBLE

日期

DataTypes.DATE       // DATETIME 适用于 mysql / sqlite, 带时区的TIMESTAMP 适用于 postgres
DataTypes.DATE(6)    // DATETIME(6) 适用于 mysql 5.6.4+. 支持6位精度的小数秒
DataTypes.DATEONLY   // 不带时间的 DATE

UUID

对于 UUID,使用 DataTypes.UUID. 对于 PostgreSQL 和 SQLite,它会是 UUID 数据类型;对于 MySQL,它则变成CHAR(36). Sequelize 可以自动为这些字段生成 UUID,只需使用 DataTypes.UUIDV1DataTypes.UUIDV4 作为默认值即可:

{
  type: DataTypes.UUID,
  defaultValue: DataTypes.UUIDV4 // 或 DataTypes.UUIDV1
}

10、数据库批量导入数据,以数组形式导入 model.bulkCreate(arr)

// 批量增加const addAll = (model, arr) => {
 return new Promise((resolve, reject) => {
  model.bulkCreate(arr)
   .then((data) => {
•    resolve(data.dataValues)
   })
   .catch(err => {
•    reject(err)
   })
 })
}

11、删除全部数据

//删除全部数据
const delAll = (model) => {
 return new Promise((resolve, reject) => {
  model.destroy({
   where: {},
   truncate: true
  })
   .then((data) => {
•    resolve(data)
   })
   .catch(err => {
•    reject(err)
   })
 })
}

12、sequelize怎么根据时间段查询

在 Sequelize 中,你可以使用 Op 对象来进行时间段查询。下面是一个示例,展示如何使用 Sequelize 查询一个指定时间段内的数据:

const { Op } = require('sequelize');
​
// 假设你有一个名为 `Event` 的模型
const Event = sequelize.define('Event', {
  // ...
});
​
// 定义开始时间和结束时间
const startTime = new Date('2022-01-01');
const endTime = new Date('2022-01-31');
​
// 使用 `Op.between` 运算符进行时间段查询
const events = await Event.findAll({
  where: {
    createdAt: {
      [Op.between]: [startTime, endTime]
    }
  }
});
​
console.log(events);

在上面的示例中,我们使用 Op.between 运算符来指定查询的时间段。Op.between 接受一个数组,数组的第一个元素是开始时间,第二个元素是结束时间。在查询中,我们使用 createdAt 字段作为时间字段,你可以根据你的模型来替换它。

请注意,Op.between 运算符是闭区间,即包括开始时间和结束时间。如果你想要排除开始时间或结束时间,你可以使用 Op.gt(大于)或 Op.lt(小于)运算符。

希望这可以帮助到你!如果你有任何其他问题,请随时问我。

13、将where的查询条件变成与的关系

要将where的查询条件变成与的关系,可以使用Sequelize中的[Op.and]操作符。下面是修改后的代码:

const { Op } = require('sequelize');
​
const data = await merchant_payout_bill.findAndCountAll({
  where: {
    store_num,
    [Op.and]: [
      { submit_time: { [Op.between]: [startTime, endTime] } }
      // 添加其他的查询条件
    ]
  },
  offset: (page_num - 1) * page_size,
  limit: page_size
});

在where对象中,使用[Op.and]操作符将多个查询条件放在一个数组中,这样它们就会被视为与的关系。你可以根据需要添加其他的查询条件到数组中。

14、根据时间字段排序

要对上面的语句进行时间段排序,可以使用order参数来指定排序方式。以下是修改后的代码:

const data = await merchant_payout_bill.findAndCountAll({
  where: {
    store_num,
    [Op.and]: [
      {
        submit_time: {
          [Op.between]: [startTime, endTime]
        }
      }
    ]
  },
  offset: (page_num - 1) * page_size,
  limit: page_size,
  order: [['submit_time', 'ASC']] // 按照 submit_time 升序排序
});

order参数中,我们使用了一个二维数组来指定排序字段和排序方式。上述代码中,我们将submit_time字段作为排序字段,并指定为升序排序(ASC)。如果要进行降序排序,可以将排序方式改为DESC

请注意,上述代码中的排序方式是按照submit_time字段进行排序的。如果你想根据其他字段进行排序,请相应地修改order参数中的字段名。

批量插入索引更新问题

1、批量插入方法,有重复数据就指定更新某些字段的值,没有重复数据就新增

   return SYSTEM_INVENTORY_BODY.bulkCreate(INVENTORYBODYS, {
        updateOnDuplicate: ["INVENTORYNUM", "REMARK"]
    })

2、判断重复数据的根据:主键ID不能重复,唯一索引值不能重复,如果因为唯一索引值无法进行插入时,可删除唯一索引或者将唯一索引类型改成普通索引