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(示例使用,字段从简)

 
  1. CREATE TABLE IF NOT EXISTS goods(

  2. id INT(20) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '商品id',

  3. name VARCHAR(64) NOT NULL COMMENT '商品名称',

  4. title VARCHAR(200) NOT NULL COMMENT '商品标题',

  5. descript TEXT COMMENT '商品描述',

  6. num BIGINT UNSIGNED NOT NULL COMMENT '商品库存',

  7. cateid INT(10) UNSIGNED NOT NULL COMMENT '分类id',

  8. price DECIMAL(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品价格',

  9. create_time DATE COMMENT '创建时间',

  10. update_time DATE COMMENT '修改时间'

  11. )ENGINE=InnoDB;

创建分类表 categorys (示例使用,字段从简)

 
  1. CREATE TABLE IF NOT EXISTS categorys(

  2. id INT(20) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '分类id',

  3. name VARCHAR(64) NOT NULL COMMENT '分类名称',

  4. create_time DATE COMMENT '创建时间',

  5. update_time DATE COMMENT '修改时间'

  6. )ENGINE=InnoDB;

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

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

引入包

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

npm install --save sequelize mysql2

连接数据库

要连接数据库,您必须new一个Sequelize的实例,给Sequelize构造函数传递参数完成连接。

 
  1. const DB = new Sequelize(database,username,password,{

  2. host:'',

  3. dialect:''

  4. })

  • database:要连接的数据库name
  • username:登录数据库时的用户名
  • password:登录数据库时的密码
  • options:选项配置参数,为一个对象,内含许多配置属性,如:
    • host:数据库主机
    • port:数据库端口号
    • dialect:指定要连接哪种类新的数据库,如:mysql、postgres等
    • define:为模型定义默认选项
    • timezone:时区

让我们先快速开始一个示例,从示例中学习需要注意的点 (请始终记住 我们使用的时准备阶段创建的数据库和表)

 
  1. const {Sequelize,Model} = require('sequelize');

  2. # 连接数据库

  3. const connect = new Sequelize('lesson','root','abc123456',{

  4. host:'localhost',

  5. port:3306,

  6. dialect:'mysql'

  7. })

  8. # 创建模型

  9. class Category extends Model{}

  10. Category.init({

  11. name:Sequelize.STRING

  12. },{

  13. sequelize:connect,

  14. tableName:'categorys'

  15. })

  16. # 新增一点数据

  17. Category.create({name:'房产'})

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

为什么会出现这个问题呢? 这是因为Sequelize为了方便开发者,它会自动帮开发者添加上创建时间和更新时间,但是它给这两个时间规定了默认字段为createdAtupdatedAt,如果不做任何配置,我们创建数据库时创建时间和修改时间字段必须与它默认规定的相同。

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

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

 
  1. # 连接数据库

  2. const connect = new Sequelize('lesson','root','abc123456',{

  3. host:'localhost',

  4. port:3306,

  5. dialect:'mysql',

  6. + define:{

  7. + timestamp:false

  8. + }

  9. })

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

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

 
  1. # 创建模型

  2. class Category extends Model{}

  3. Category.init({

  4. name:Sequelize.STRING,

  5. + update_time:{

  6. + type:Sequelize.DATE

  7. + }

  8. },{

  9. sequelize:connect,

  10. tableName:'categorys'

  11. })

  12. # 新增一点数据

  13. + const create_time = new Date().getTime();

  14. Category.create({name:'房产',create_time:create_time})

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

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

当然,我们开启了timestamp,数据库的时间字段也可以是任意合法的字符。 这时候需要我们配置字段别名,这是很简单的,只需要添加两行代码就可以了,如下:

 
  1. # 连接数据库

  2. const connect = new Sequelize('lesson','root','abc123456',{

  3. host:'localhost',

  4. port:3306,

  5. dialect:'mysql',

  6. + define:{

  7. + timestamp:true,

  8. + createdAt:'create_time',

  9. + updatedAt:'update_time'

  10. + }

  11. })

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

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

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

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

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

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

 
  1. Category.init({

  2. name:{

  3. type:Sequelize.STRING,

  4. set(val){

  5. const newVal = val + 'sb'; // 所有添加的数据 name后都加上sb字符

  6. this.setDataValue('name',newVal);

  7. },

  8. get() {

  9. const rawValue = this.getDataValue('name'); //获取字段值

  10. return rawValue ? rawValue.toUpperCase() : null; //将字段值的字母转换成大写输出

  11. }

  12. },

  13. vitName:{ // 这是一个虚拟字段

  14. type:Sequelize.VIRTUAL,

  15. get(){

  16. return `${this.name}`

  17. }

  18. }

  19. },{

  20. sequelize:connect,

  21. tableName:'categorys'

  22. })

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

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

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

查询选择器:

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

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

所有商品:

 
  1. router.get('/pro/list',async (ctx,next) => {

  2. const result = await Product.findAll();

  3. ctx.body = {

  4. msg:result

  5. }

  6. })

得到的结果为:

 
  1. {

  2. "msg": [

  3. {

  4. "id": 2,

  5. "name": "工装七分裤",

  6. "title": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ",

  7. "descript": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO 优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ",

  8. "num": 158,

  9. "cateid": 2,

  10. "price": "149.00",

  11. "create_time": "2020-07-25",

  12. "update_time": "2020-07-25"

  13. },

  14. {

  15. "id": 3,

  16. "name": "花花公子旗舰短袖t恤",

  17. "title": "花花公子旗舰短袖t恤男2020新款夏季潮牌宽松男士半袖潮流打底衫T ",

  18. "descript": "花花公子旗舰短袖t恤男2020新款夏季潮牌宽松男士半袖潮流打底衫T 花花公子旗舰短袖t恤男2020新款夏季潮牌宽松男士半袖潮流打底衫T ",

  19. "num": 3000,

  20. "cateid": 2,

  21. "price": "269.00",

  22. "create_time": "2020-07-25",

  23. "update_time": "2020-07-25"

  24. },

  25. {

  26. "id": 4,

  27. "name": "华为nova",

  28. "title": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店 ",

  29. "descript": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店",

  30. "num": 2500,

  31. "cateid": 3,

  32. "price": "1999.00",

  33. "create_time": "2020-07-25",

  34. "update_time": "2020-07-25"

  35. },

  36. {

  37. "id": 5,

  38. "name": "荣耀30",

  39. "title": "华为旗下荣耀30新品5G手机50倍超稳远摄麒麟985芯片全新智能手机正品官方旗舰店",

  40. "descript": "华为旗下荣耀30新品5G手机50倍超稳远摄麒麟985芯片全新智能手机正品官方旗舰店华为旗下荣耀30新品5G手机50倍超稳远摄麒麟985芯片全新智能手机正品官方旗舰店",

  41. "num": 3512,

  42. "cateid": 3,

  43. "price": "3299.00",

  44. "create_time": "2020-07-25",

  45. "update_time": "2020-07-25"

  46. },

  47. {

  48. "id": 6,

  49. "name": "美的变频空调",

  50. "title": "美的i青春大1.5匹空调智能挂机冷暖壁挂式官方旗舰店",

  51. "descript": "美的i青春大1.5匹空调智能挂机冷暖壁挂式官方旗舰店美的i青春大1.5匹空调智能挂机冷暖壁挂式官方旗舰店",

  52. "num": 4215,

  53. "cateid": 4,

  54. "price": "2999.00",

  55. "create_time": "2020-07-25",

  56. "update_time": "2020-07-25"

  57. },

  58. {

  59. "id": 7,

  60. "name": "格力Gree",

  61. "title": "Gree/格力 KFR-35GW 大1.5匹空调挂机智能变频冷暖一级壁挂式品悦",

  62. "descript": "Gree/格力 KFR-35GW 大1.5匹空调挂机智能变频冷暖一级壁挂式品悦Gree/格力 KFR-35GW 大1.5匹空调挂机智能变频冷暖一级壁挂式品悦",

  63. "num": 4215,

  64. "cateid": 4,

  65. "price": "4199.00",

  66. "create_time": "2020-07-25",

  67. "update_time": "2020-07-25"

  68. },

  69. {

  70. "id": 8,

  71. "name": "郁香菲2020夏季新品",

  72. "title": "郁香菲2020夏季新品 荷叶边两穿收腰长款连衣裙纯色垂感飘逸长裙 ",

  73. "descript": "郁香菲2020夏季新品 荷叶边两穿收腰长款连衣裙纯色垂感飘逸长裙 郁香菲2020夏季新品 荷叶边两穿收腰长款连衣裙纯色垂感飘逸长裙 ",

  74. "num": 4215,

  75. "cateid": 5,

  76. "price": "699.00",

  77. "create_time": "2020-07-25",

  78. "update_time": "2020-07-25"

  79. },

  80. {

  81. "id": 9,

  82. "name": "美背文胸",

  83. "title": "运动内衣女无钢圈聚拢冰丝无痕背心式胸罩夏季薄款调整型美背文胸 ",

  84. "descript": "运动内衣女无钢圈聚拢冰丝无痕背心式胸罩夏季薄款调整型美背文胸 运动内衣女无钢圈聚拢冰丝无痕背心式胸罩夏季薄款调整型美背文胸 ",

  85. "num": 10000,

  86. "cateid": 5,

  87. "price": "99.00",

  88. "create_time": "2020-07-25",

  89. "update_time": "2020-07-25"

  90. }

  91. ]

  92. }

条件查询

查询

 
  1. router.get('/pro/list',async (ctx,next) => {

  2. const result = await Product.findAll({

  3. where:{

  4. id:4

  5. }

  6. });

  7. ctx.body = {

  8. msg:result

  9. }

  10. })

结果:

 
  1. {

  2. "msg": [

  3. {

  4. "id": 4,

  5. "name": "华为nova",

  6. "title": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店 ",

  7. "descript": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店",

  8. "num": 2500,

  9. "cateid": 3,

  10. "price": "1999.00",

  11. "create_time": "2020-07-25",

  12. "update_time": "2020-07-25"

  13. }

  14. ]

  15. }

查询

 
  1. router.get('/pro/list',async (ctx,next) => {

  2. const result = await Product.findOne({

  3. where:{

  4. id:4

  5. }

  6. });

  7. ctx.body = {

  8. msg:result

  9. }

  10. })

  11. # 等同于

  12. router.get('/pro/list',async (ctx,next) => {

  13. const result = await Product.findByPk(4);

  14. ctx.body = {

  15. msg:result

  16. }

  17. })

结果一样,都是

 
  1. {

  2. "msg": {

  3. "id": 4,

  4. "name": "华为nova",

  5. "title": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店 ",

  6. "descript": "Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰Huawei/华为 nova6 SE超级快充4800万AI四摄大运存nova6se 华为手机华为官方旗舰店",

  7. "num": 2500,

  8. "cateid": 3,

  9. "price": "1999.00",

  10. "create_time": "2020-07-25",

  11. "update_time": "2020-07-25"

  12. }

  13. }

注意:findAll和findOne、findByPk方法得到的结果是不同的,findAll得到的结果是数组包含着数据项,而findOne、findByPk得到的结果就是一条数据

分页查询

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

  • offset:偏移量,以0开始做偏移
  • limit:限制条数

值得我们注意的是offset是以0开始做偏移的,通常前端分页会传递两个参数:pageCurrentpageSize。 pageCurrent通常是以1开始的。所以后端接收到pageCurrent后需要减1传递给Sequelize做偏移。

 
  1. router.get('/pro/list',async (ctx,next) => {

  2. const { pageCurrent,pageSize } = ctx.request.body;

  3. let limit = pageSize ? pageSize : limit;

  4. let offset = pageCurrent ? (pageCurrent - 1)*limit : offset;

  5. const result = await Product.findAll({

  6. offset,

  7. limit

  8. });

  9. ctx.body = {

  10. msg:result

  11. }

  12. })

指定字段

 
  1. router.get('/pro/list',async (ctx,next) => {

  2. const result = await Product.findOne({

  3. attributes:['name','price']

  4. });

  5. ctx.body = {

  6. msg:result

  7. }

  8. })

结果

 
  1. {

  2. "msg": {

  3. "name": "工装七分裤",

  4. "price": "149.00"

  5. }

  6. }

排除字段

 
  1. router.get('/pro/list',async (ctx,next) => {

  2. const result = await Product.findOne({

  3. attributes:{

  4. exclude:['descript']

  5. }

  6. });

  7. ctx.body = {

  8. msg:result

  9. }

  10. })

结果

 
  1. {

  2. "msg": {

  3. "id": 2,

  4. "name": "工装七分裤",

  5. "title": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ",

  6. "num": 158,

  7. "cateid": 2,

  8. "price": "149.00",

  9. "create_time": "2020-07-25",

  10. "update_time": "2020-07-25"

  11. }

  12. }

排序查询

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

 
  1. router.get('/pro/list',async (ctx,next) => {

  2. const result = await Product.findAll({

  3. order:[

  4. ['id','desc']

  5. ]

  6. });

  7. ctx.body = {

  8. msg:result

  9. }

  10. })

关联查询

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

  • hasOne关联:与目标建立一对一关联关系,外键存在于目标模型中
  • belongsTo关联:与目标建立一对一关联关系,外键存在于源模型中
  • hasMany:与目标建立一对多关联关系,外键存在于目标模型中
  • belongsToMany:与目标建立多对多关联关系,外键存在于源模型中
 
  1. # 外键存在于源模型中

  2. Product.belongsTo(Category,{

  3. foreignKey:'cateid',

  4. targetKey:'id'

  5. })

  6. # 外键存在于目标模型中

  7. Product.hasOne(Category,{

  8. as:'cate',

  9. foreignKey:'id',

  10. targetKey:'cateid'

  11. })

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

示例代码:

 
  1. Product.hasOne(Category,{

  2. foreignKey:'id',

  3. targetKey:'cateid'

  4. })

  5. router.get('/pro/list',async (ctx,next) => {

  6. const result = await Product.findOne({

  7. include:{

  8. model:Category

  9. }

  10. });

  11. ctx.body = {

  12. msg:result

  13. }

  14. })

得到结果:

 
  1. {

  2. "msg": {

  3. "id": 2,

  4. "name": "工装七分裤",

  5. "title": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ",

  6. "descript": "优衣库 男装 工装七分裤(卷边) 425146 UNIQLO 优衣库 男装 工装七分裤(卷边) 425146 UNIQLO ",

  7. "num": 158,

  8. "cateid": 2,

  9. "price": "149.00",

  10. "create_time": "2020-07-25",

  11. "update_time": "2020-07-25",

  12. "Category": {

  13. "id": 2,

  14. "name": "男装",

  15. "create_time": "2020-07-25",

  16. "update_time": "2020-07-25"

  17. }

  18. }

  19. }

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

 
  1. Product.hasOne(Category,{

  2. + as:'cate',

  3. foreignKey:'id',

  4. targetKey:'cateid'

  5. })

  6. router.get('/pro/list',async (ctx,next) => {

  7. const result = await Product.findOne({

  8. include:{

  9. model:Category,

  10. + as:'cate'

  11. }

  12. });

  13. ctx.body = {

  14. msg:result

  15. }

  16. })

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

Category.update(param,option)

  • param:修改的参数集合,Object
  • option:配置选项
 
  1. router.post('/edit',async (ctx,next) => {

  2. await Category.update({

  3. name:'男装内裤'

  4. },{

  5. where:{

  6. id:2

  7. }

  8. })

  9. })

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

Category.destroy(option)

彻底掌握NodeJS中如何使用Sequelize相关推荐

  1. mysql 主键 uniqo_项目总结,彻底掌握NodeJS中如何使用Sequelize

    前言 sequelize是什么? sequelize是基于NodeJs的ORM框架,它适用于不同的数据库,如:Postgres.MySQL.SQLite.MariaDB,我们可以通过sequelize ...

  2. 记录nodejs使用express搭建一个api服务器程序(5)-nodejs操作SQL数据库,Sequelize和Knex

    此文章是我自己用来记录如何搭建一个以express为基础的api服务器框架的过程,并不是什么新手教程,并不会每一步都写得非常详细,如果您要阅读此文,需要一点nodejs和编写代码的基础知识 文接上篇 ...

  3. nodejs+html转换pdf,Nodejs中使用phantom将html转为pdf或图片格式的方法

    最近在项目中遇到需要把html页面转换为pdf的需求,并且转换成的pdf文件要保留原有html的样式和图片.也就是说,html页面的图片.表格.样式等都需要完整的保存下来. 最初找到三种方法来实现这个 ...

  4. nodeJS中读写文件方法的区别

    导言:nodejs中所有与文件相关的操作都在fs模块中,而读写操作又是我们会经常用到的操作,nodejs的fs模块针对读操作为我们提供了readFile,read, createReadStream三 ...

  5. nodejs+html转换pdf,Nodejs中使用phantom将html转为pdf或图片格式的方法.pdf

    Nodejs中中使使用用phantom将将html转转为为pdf或或图图片片格格式式的的方方法法 最近在项目中遇到需要把html页面转换为pdf 的需求,并且转换 的pdf文件要保留原有html的样式 ...

  6. 理解nodejs中函数的参数的来由

    看一段创建并启动nodejs服务的代码,如下: var http = require('http');http.createServer(function (request, response) {r ...

  7. Nodejs中搭建一个静态Web服务器,通过读取文件获取响应类型

    场景 Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档,也可以放置网站文件让全世界浏览,还可以放置数据文件,让全世界下载.目前最主流的Web服务 ...

  8. Nodejs中的模块系统

    一.模块化的定义 ①具有文件作用域 ②具有通信规则:加载和导出规则 二.CommonJS模块规范 1.nodejs中的模块系统,具有文件作用域,也具有通信规则,使用require方法加载模块,使用ex ...

  9. 不要在nodejs中阻塞event loop

    文章目录 简介 event loop和worker pool event loop和worker pool中的queue 阻塞event loop event loop的时间复杂度 Event Loo ...

  10. nodejs中使用worker_threads来创建新的线程

    文章目录 简介 worker_threads isMainThread MessageChannel parentPort和MessagePort markAsUntransferable SHARE ...

最新文章

  1. 270个开源项目,总计24w星,帮你快速找代码
  2. Nature会议:驾驭植物微生物组(21年10月22-24,在线,优惠截止9月24日)
  3. KDD2021最佳论文奖揭晓!胡侠获新星奖,论文接收率仅15%
  4. Unix高级环境编程 学习小结(一)
  5. 创建 linuxrc 文件
  6. Redis主从配置和集群配置
  7. Android ListView分页,动态添加数据
  8. 简单理解下内存的几大区域
  9. 《王道》数据结构笔记整理2022
  10. Eclipse语言包的安装与卸载
  11. Dev C++中编译问题
  12. 报文解析_101规约报文格式定义解析
  13. 如何美化CheckBox
  14. OSChina 周六乱弹 ——揭秘后羿怎么死的
  15. ADDA数模转换(PCF8591)
  16. 3天完成Open CPU开发!7天完成Costdown
  17. SSM整合步骤(超详细)
  18. Unity学习之Human fall flat创意工坊地图制作
  19. 链表-1(链表理论基础、移除链表元素、设计链表翻转链表)
  20. 谷歌机器学习主管:10年自学数据科学的3点心得体会

热门文章

  1. Python学习手册之函数和模块
  2. 深入理解Risk aversion||风险偏好||Risk utility function
  3. 指纹采集器测试软件,售完存档:小熊做的关于奔凯BIOCOME USB指纹采集器 指纹识别仪TCR4 Win7 Win8 Win10下的使用教程...
  4. 2021-12-23 714. 买卖股票的时机含手续费(动态规划)
  5. Jetson TX2 学习笔记(2) —— 挂载外接硬盘与分区
  6. 真正准确的“两个日期相差多少天”函数
  7. 【优雅解决】:换源后 sudo apt-get update 出现 N: Updating from such a repository can't be done securely……
  8. php 生成条码插件,PHP版条码生成器
  9. Java抽象类、接口理解
  10. 猫哥教你写爬虫 019--debug-作业