allbet欧博真人客户端:项目总结,彻底掌握NodeJS中若何使用Sequelize

admin/2020-07-28/ 分类:科技/阅读:

前言

sequelize是什么? sequelize是基于NodeJs的ORM框架,它适用于差别的数据库,如:Postgres、MySQL、SQLite、MariaDB,我们可以通过sequelize对数据库举行一系列的操作。通常我用它与MySQL一起使用。该文是我在使用sequelize做完项目后对sequelize的系统整理。

准备工作

一、确立数据库和表,利便学习过程中誊写示例代码

确立数据库 lesson

CREATE DATABASE IF NOT EXISTS lesson DEFAULT CHARSET utf8 COLLATE utf8_general_ci; 

确立商品表 goods(示例使用,字段从简)

CREATE TABLE IF NOT EXISTS goods( id INT(20) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '商品id', name VARCHAR(64) NOT NULL COMMENT '商品名称', title VARCHAR(200) NOT NULL COMMENT '商品题目', descript TEXT COMMENT '商品形貌', num BIGINT UNSIGNED NOT NULL COMMENT '商品库存', cateid INT(10) UNSIGNED NOT NULL COMMENT '分类id', price DECIMAL(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品价格', create_time DATE COMMENT '确立时间', update_time DATE COMMENT '修改时间' )ENGINE=InnoDB; 

确立分类表 categorys (示例使用,字段从简)

CREATE TABLE IF NOT EXISTS categorys( id INT(20) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '分类id', name VARCHAR(64) NOT NULL COMMENT '分类名称', create_time DATE COMMENT '确立时间', update_time DATE COMMENT '修改时间' )ENGINE=InnoDB; 

二、使用koa框架起一个服务

要学习使用sequelize,我们要先用node搭建基础服务,露出接口利便测试,直观的看到代码效果。

引入包

在使用sequelize之前,我们需要引入两个包:sequelize、mysql2

npm install --save sequelize mysql2 

毗邻数据库

要毗邻数据库,您必须new一个Sequelize的实例,给Sequelize组织函数通报参数完成毗邻。

const DB = new Sequelize(database,username,password,{ host:'', dialect:'' }) 
  • database:要毗邻的数据库name
  • username:登录数据库时的用户名
  • password:登录数据库时的密码
  • options:选项设置参数,为一个工具,内含许多设置属性,如:
    • host:数据库主机
    • port:数据库端口号
    • dialect:指定要毗邻哪种类新的数据库,如:mysql、postgres等
    • define:为模子界说默认选项
    • timezone:时区

让我们先快速最先一个示例,从示例中学习需要注重的点 (请始终记着 我们使用的时准备阶段确立的数据库和表)

const {Sequelize,Model} = require('sequelize'); # 毗邻数据库 const connect = new Sequelize('lesson','root','abc123456',{ host:'localhost', port:3306, dialect:'mysql' }) # 确立模子 class Category extends Model{} Category.init({ name:Sequelize.STRING },{ sequelize:connect, tableName:'categorys' }) # 新增一点数据 Category.create({name:'房产'}) 

当我们运行代码新增数据时,会发现数据没有添加乐成且控制台报错。

为什么会泛起这个问题呢? 这是由于Sequelize为了利便开发者,它会自动帮开发者添加上确立时间和更新时间,然则它给这两个时间划定了默认字段为createdAtupdatedAt,若是不做任何设置,我们确立数据库时确立时间和修改时间字段必须与它默认划定的相同。

与这两个字段相关联的有一个timestamp设置属性,这个属性可以启用或不启用Sequelize为开发者自动添加时间,默以为true。

对上面代码做一点点更改,如下:

# 毗邻数据库 const connect = new Sequelize('lesson','root','abc123456',{ host:'localhost', port:3306, dialect:'mysql', define:{ timestamp:false } }) 

在实例化Sequelize时,加上define参数设置,可以作用于全局。 我们如上设置全局timestamp为false,即示意关闭自动添加时间,再次运行代码 我们会发现数据库添加了一条数据。

解决了上面添加数据失败的问题,然则没有确立时间,这显然不是我们所希望的。 我们再对代码做一些改动,添加上create_time字段如下:

# 确立模子 class Category extends Model{} Category.init({ name:Sequelize.STRING, update_time:{ type:Sequelize.DATE } },{ sequelize:connect, tableName:'categorys' }) # 新增一点数据 const create_time = new Date().getTime(); Category.create({name:'房产',create_time:create_time}) 

这时再打开数据库,我们可以看到有一条具有确立时间的数据已经被添加上去了

做到这里,我们知道了,不用Sequelize自动添加时间的方式,我们可以自己手动编码添加,而且数据库的时间字段可以是随便正当的字符。

固然,我们开启了timestamp,数据库的时间字段也可以是随便正当的字符。 这时候需要我们设置字段别名,这是很简朴的,只需要添加两行代码就可以了,如下:

# 毗邻数据库 const connect = new Sequelize('lesson','root','abc123456',{ host:'localhost', port:3306, dialect:'mysql', define:{ timestamp:true, createdAt:'create_time', updatedAt:'update_time' } }) 

上述篇幅,我们已经知道若何毗邻数据库和向数据库中添加数据,然则有些营业场景,不仅仅只是将我们在输入框中的数据原样插入到数据库中,可能会对输入的数据做一些改动,如用户注册时,密码需要加密然后再插入到数据库中。

需要实现这个需求,我们需要学习Sequelize的Setters、Getters和Virtuals

Setters: setter是为模子中字段的set()函数,它吸收字段的值。它作用在数据的添加阶段,在set()函数中,我们可以获取字段的值并对原始值做一系列的转变,然后再设置最终值。

Getters: getter是为模子中字段的get()函数,它作用在数据的获取阶段,在get()函数中,我们可以先对返回值做一系列的操作,再返回最终值。

Virtuals: virtuals是虚拟字段,它不存在与数据库中。开发者可以使用它将两个字段拼接返回。

接下来我们来看看实际使用的栗子,代码如下:

Category.init({ name:{ type:Sequelize.STRING, set(val){ const newVal = val 'sb'; // 所有添加的数据 name后都加上sb字符 this.setDataValue('name',newVal); }, get() { const rawValue = this.getDataValue('name'); //获取字段值 return rawValue ? rawValue.toUpperCase() : null; //将字段值的字母转换成大写输出 } }, vitName:{ // 这是一个虚拟字段 type:Sequelize.VIRTUAL, get(){ return `${this.name}` } } },{ sequelize:connect, tableName:'categorys' }) 

到现在,我们已经学习了Sequelize许多的知识点了,接下来我们继续学习Sequelize的查询、修改、删除等方式。 在学习之前 我们照样先将数据库的数据维护一份正式一点的数据。

分别是分类表和商品表 如下图:

Sequelize为开发者提供了查找方式,默认情况下,所有查找器方式的效果都是模子类的实例,而不是简朴的javascript工具。这意味着在数据库返回效果后,Sequelize会自动将所有内容打包到适当的实例工具中。在某些情况下,当效果太多时,这种包装可能效率低下,可以通过{raw:true}选项设置禁用。

查询选择器:

  • findAll:它天生一条尺度的SELECT查询语句,在不受到条件语句限制的情况下从表中检索所有数据。
  • findByPk:凭据提供的主键,从表中检索处一条数据。
  • findOne:若是不提供查询选项的话,它会检索到表中第一条数据。
  • count:检索数据库中所有数据,获得数据总数。
  • findAndCountAll:可以获得数据总量和数据列表。这在做分页数据时时异常利便的。

现在我们来查询表数据,实现一些需求。

所有商品:
router.get('/pro/list',async (ctx,next) => { const result = await Product.findAll(); ctx.body = { msg:result } }) 

获得的效果为:

{ "msg": [ { "id": 2, "name": "工装七分裤", "title": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ", "descript": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO 优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ", "num": 158, "cateid": 2, "price": "149.00", "create_time": "2020-07-25", "update_time": "2020-07-25" }, { "id": 3, "name": "花花公子旗舰短袖t恤", "title": "花花公子旗舰短袖t恤男2020新款夏日潮牌宽松男士半袖潮水打底衫T ", "descript": "花花公子旗舰短袖t恤男2020新款夏日潮牌宽松男士半袖潮水打底衫T 花花公子旗舰短袖t恤男2020新款夏日潮牌宽松男士半袖潮水打底衫T ", "num": 3000, "cateid": 2, "price": "269.00", "create_time": "2020-07-25", "update_time": "2020-07-25" }, { "id": 4, "name": "华为nova", "title": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店 ", "descript": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店", "num": 2500, "cateid": 3, "price": "1999.00", "create_time": "2020-07-25", "update_time": "2020-07-25" }, { "id": 5, "name": "荣耀30", "title": "华为旗下荣耀30新品5G手机50倍超稳远摄麒麟985芯片全新智能手机正品官方旗舰店", "descript": "华为旗下荣耀30新品5G手机50倍超稳远摄麒麟985芯片全新智能手机正品官方旗舰店华为旗下荣耀30新品5G手机50倍超稳远摄麒麟985芯片全新智能手机正品官方旗舰店", "num": 3512, "cateid": 3, "price": "3299.00", "create_time": "2020-07-25", "update_time": "2020-07-25" }, { "id": 6, "name": "美的变频空调", "title": "美的i青春大1.5匹空调智能挂机冷暖壁挂式官方旗舰店", "descript": "美的i青春大1.5匹空调智能挂机冷暖壁挂式官方旗舰店美的i青春大1.5匹空调智能挂机冷暖壁挂式官方旗舰店", "num": 4215, "cateid": 4, "price": "2999.00", "create_time": "2020-07-25", "update_time": "2020-07-25" }, { "id": 7, "name": "格力Gree", "title": "Gree/格力 KFR-35GW 大1.5匹空调挂机智能变频冷暖一级壁挂式品悦", "descript": "Gree/格力 KFR-35GW 大1.5匹空调挂机智能变频冷暖一级壁挂式品悦Gree/格力 KFR-35GW 大1.5匹空调挂机智能变频冷暖一级壁挂式品悦", "num": 4215, "cateid": 4, "price": "4199.00", "create_time": "2020-07-25", "update_time": "2020-07-25" }, { "id": 8, "name": "郁香菲2020夏日新品", "title": "郁香菲2020夏日新品 荷叶边两穿收腰长款连衣裙纯色垂感萧洒长裙 ", "descript": "郁香菲2020夏日新品 荷叶边两穿收腰长款连衣裙纯色垂感萧洒长裙 郁香菲2020夏日新品 荷叶边两穿收腰长款连衣裙纯色垂感萧洒长裙 ", "num": 4215, "cateid": 5, "price": "699.00", "create_time": "2020-07-25", "update_time": "2020-07-25" }, { "id": 9, "name": "美背文胸", "title": "运动亵服女无钢圈聚拢冰丝无痕背心式胸罩夏日薄款调整型美背文胸 ", "descript": "运动亵服女无钢圈聚拢冰丝无痕背心式胸罩夏日薄款调整型美背文胸 运动亵服女无钢圈聚拢冰丝无痕背心式胸罩夏日薄款调整型美背文胸 ", "num": 10000, "cateid": 5, "price": "99.00", "create_time": "2020-07-25", "update_time": "2020-07-25" } ] } 
条件查询

查询

router.get('/pro/list',async (ctx,next) => { const result = await Product.findAll({ where:{ id:4 } }); ctx.body = { msg:result } }) 

效果:

{ "msg": [ { "id": 4, "name": "华为nova", "title": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店 ", "descript": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店", "num": 2500, "cateid": 3, "price": "1999.00", "create_time": "2020-07-25", "update_time": "2020-07-25" } ] } 

查询

router.get('/pro/list',async (ctx,next) => { const result = await Product.findOne({ where:{ id:4 } }); ctx.body = { msg:result } }) # 等同于 router.get('/pro/list',async (ctx,next) => { const result = await Product.findByPk(4); ctx.body = { msg:result } }) 

效果一样,都是

{ "msg": { "id": 4, "name": "华为nova", "title": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店 ", "descript": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店", "num": 2500, "cateid": 3, "price": "1999.00", "create_time": "2020-07-25", "update_time": "2020-07-25" } } 

注重:findAll和findOne、findByPk方式获得的效果是差别的,findAll获得的效果是数组包含着数据项,而findOne、findByPk获得的效果就是一条数据

分页查询

我们在项目中经常会需要分页查询,一次性查询所有的数据,无论是服务器照样前端页面显示都是不友好的。Sequelize为开发者提供了分页机制,我们只需设置offsetlimit两个属性就可以实现分页。

  • offset:偏移量,以0最先做偏移
  • limit:限制条数

值得我们注重的是offset是以0最先做偏移的,通常前端分页会通报两个参数:pageCurrentpageSize。 pageCurrent通常是以1最先的。以是后端吸收到pageCurrent后需要减1通报给Sequelize做偏移。

router.get('/pro/list',async (ctx,next) => { const { pageCurrent,pageSize } = ctx.request.body; let limit = pageSize ? pageSize : limit; let offset = pageCurrent ? (pageCurrent - 1)*limit : offset; const result = await Product.findAll({ offset, limit }); ctx.body = { msg:result } }) 
指定字段
router.get('/pro/list',async (ctx,next) => { const result = await Product.findOne({ attributes:['name','price'] }); ctx.body = { msg:result } }) 

效果

{ "msg": { "name": "工装七分裤", "price": "149.00" } } 
清扫字段
router.get('/pro/list',async (ctx,next) => { const result = await Product.findOne({ attributes:{ exclude:['descript'] } }); ctx.body = { msg:result } }) 

效果

{ "msg": { "id": 2, "name": "工装七分裤", "title": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ", "num": 158, "cateid": 2, "price": "149.00", "create_time": "2020-07-25", "update_time": "2020-07-25" } } 
排序查询

设置order选项,order是一个数组,字段名和排序方式。 desc(降序),asc(升序)

router.get('/pro/list',async (ctx,next) => { const result = await Product.findAll({ order:[ ['id','desc'] ] }); ctx.body = { msg:result } }) 
关联查询

sequelize提供了四种类型的关联关系

  • hasOne关联:与目的确立一对一关联关系,外键存在于目的模子中
  • belongsTo关联:与目的确立一对一关联关系,外键存在于源模子中
  • hasMany:与目的确立一对多关联关系,外键存在于目的模子中
  • belongsToMany:与目的确立多对多关联关系,外键存在于源模子中
# 外键存在于源模子中 Product.belongsTo(Category,{ foreignKey:'cateid', targetKey:'id' }) # 外键存在于目的模子中 Product.hasOne(Category,{ as:'cate', foreignKey:'id', targetKey:'cateid' }) 

上面两个代码示例, Product模子是源模子,Category模子是目的模子。cateid是Product中界说的字段列,可以看到使用belongsTo时外键foreignKey的值是cateid 使用hasOne时外键foreignKey的值是id ,这个id是Category中的主键id。

示例代码:

Product.hasOne(Category,{ foreignKey:'id', targetKey:'cateid' }) router.get('/pro/list',async (ctx,next) => { const result = await Product.findOne({ include:{ model:Category } }); ctx.body = { msg:result } }) 

获得效果:

{ "msg": { "id": 2, "name": "工装七分裤", "title": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ", "descript": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO 优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ", "num": 158, "cateid": 2, "price": "149.00", "create_time": "2020-07-25", "update_time": "2020-07-25", "Category": { "id": 2, "name": "男装", "create_time": "2020-07-25", "update_time": "2020-07-25" } } } 

商品信息中就有了该商品所属分类的信息,可以看到返回的商品信息字段是Category即是以界说的类名Category为字段,我们可以更改它。

Product.hasOne(Category,{ as:'cate', foreignKey:'id', targetKey:'cateid' }) router.get('/pro/list',async (ctx,next) => { const result = await Product.findOne({ include:{ model:Category, as:'cate' } }); ctx.body = { msg:result } }) 

这样分类信息的字段就跟更改成了cate

Category.update(param,option)

  • param:修改的参数聚集,Object
  • option:设置选项
router.post('/edit',async (ctx,next) => { await Category.update({ name:'男装内裤' },{ where:{ id:2 } }) }) 

上面代码 修改id即是2的那条数据,将name字段的值更改为'男装内裤'。

Category.destroy(option)

Category.destroy({ where:{ id:2 } }) 
,

欧博亚洲APP下载

欢迎进入欧博亚洲APP下载(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

TAG:
阅读:
广告 330*360
广告 330*360
Sunbet_进入申博sunbet官网
微信二维码扫一扫
关注微信公众号
新闻自媒体 Copyright © 2002-2019 Sunbet 版权所有
二维码
意见反馈 二维码