美文网首页
使用Sequelize操作MySQL

使用Sequelize操作MySQL

作者: royluck | 来源:发表于2019-09-25 14:19 被阅读0次
Sequelize ORM 实践

由于sequelize依赖于mysql2所以也需要安装mysql2:
npm install mysql2 --save
创建数据库:
字符集:utf8mb4
排序规则:utf8mb4_genaral_ci
字段数据类型:

字段数据类型

const {Sequelize,Model} = require('sequelize')
const {unset, clone, isArray} = require('lodash')
const {
    dbName,
    host,
    port,
    user,
    password
} = require('../config/config1').database

const sequelize = new Sequelize(dbName,user,password,{
    dialect:'mysql',
    host,
    port,
    logging:true,
  
    timezone: '+08:00',
    // 个性化配置
    define:{
        //create_time  update_time delete_time
        timestamps:true,
        paranoid:true, // 开启软删除
        createdAt:'created_at',  // 自定义字段名,默认为'createdAt',将其改为'created_at'
        updatedAt:'updated_at',
        deletedAt:'deleted_at',
        underscored:true,  // 字段驼峰转下划线
        // 禁止修改表名,默认情况下,sequelize将自动将所有传递的模型名称(define的第一个参数)转换为复数
        // 但是为了安全着想,复数的转换可能会发生变化,所以禁止该行为
        freezeTableName:true,
        scopes:{
            bh:{ // 过滤不必要的字段(这里会有bug)
                attributes:{
                    exclude:['updated_at','deleted_at','created_at']
                }
            }
        }
    }
})

sequelize.sync({
    force:false  // true 清空数据库表
})

Model.prototype.toJSON= function(){
    // let data = this.dataValues
    let data = clone(this.dataValues)
    unset(data, 'updated_at')
    unset(data, 'created_at')
    unset(data, 'deleted_at')

    for (key in data){
        if(key === 'image'){
            if(!data[key].startsWith('http'))
                data[key]=global.config.host + data[key]
        }
    }

    if(isArray(this.exclude)){
        this.exclude.forEach(
            (value)=>{
                unset(data,value)
            }
        )
    }
    // this.exclude
    // exclude
    // a,b,c,d,e
    return data
}

module.exports = {
    sequelize
}

数字类型查询比字符串查询快


Sequelize 中文API文档-5. 实例的使用、Instance类介绍:
  • findOne:
async validateEmail(vals) {
        const email = vals.body.email
        const user = await User.findOne({
            where: {
                email: email
            }
        })
        if (user) {
            throw new Error('email已存在')
        }
    }
  • setDataValue:
static _getEachBookStatus(book, favors){
        let count = 0
        favors.forEach(favor=>{
            if(book.id === favor.art_id){
                count = favor.get('count')
            }
        })
        book.setDataValue('fav_nums',count)
        return book
    }
  • count:
 static async getMyFavorBookCount(uid) {
        const count = await Favor.count({
            where: {
                type: 400,
                uid
            }
        })
        return count
    }

increment
decrement

static async getAll(){
        const books =await HotBook.findAll({
            // 排序
            order:[
                'index'
            ]
        })
        const ids = []
        books.forEach((book)=>{
            ids.push(book.id)
        })
        const favors =await Favor.findAll({
            where:{
                art_id:{
                    [Op.in]:ids,
                },
                type:400
            },
            group:['art_id'], // 排序
            attributes:['art_id', [Sequelize.fn('COUNT','*'),'count']]
        })
        books.forEach(book=>{
             HotBook._getEachBookStatus(book, favors)
        })
        //python 二维矩阵
        return books
    }

linvalidator:

module-alias别名包

lin-cms 不能拦截sequelize的错误???
Unhandled rejection SequelizeValidationError: string violation: banner cannot be an array or an object
Unhandled rejection SequelizeDatabaseError: Unknown column 'place_orders_nums' in 'field list'

class ProductDao {
  async createGoods (v) {
    /** 这里需要创建多个表
     * 1:商品表
     * 2:规格值表
     * 3:商品和规格关系表
     * 4:sku表
     * 创建商品 */
    const goods = new Product();
    goods.name = v.get('body.name');
    goods.banner = v.get('body.banner');
    goods.desc_imgs = v.get('body.descImg');
    goods.cate_id = 22;
    return goods.save();  // 开始没有加return,所以没捕获到,加了return就可以了
  }
}

attributes:
  • attributes:['art_id', [Sequelize.fn('COUNT','*'),'count']] // 内置方法
  • attributes:决定返回什么字段
static async getAll(){
        const books =await HotBook.findAll({
            order:[
                'index'
            ]
        })
        const ids = []
        books.forEach((book)=>{
            ids.push(book.id)
        })
        const favors =await Favor.findAll({
            where:{
                art_id:{
                    [Op.in]:ids,
                },
                type:400
                // 国画
                // 漫画
            },
            group:['art_id'],
            attributes:['art_id', [Sequelize.fn('COUNT','*'),'count']]
        })
        books.forEach(book=>{
             HotBook._getEachBookStatus(book, favors)
        })
        //python 二维矩阵
        return books
    }

SQL语句:
async getUserNames (start, count) {
    const logs = await db.query(
      'SELECT lin_log.user_name AS names FROM lin_log GROUP BY lin_log.user_name HAVING COUNT(lin_log.user_name)>0 limit :count offset :start',
      {
        replacements: {
          start: start * count,
          count: count
        }
      }
    );
    const arr = Array.from(logs[0].map(it => it['names']));
    return arr;
  }

Sequelize写入数据库有两种方式:

1、通过实例
save

async updateGroup (ctx, v) {
    const id = v.get('path.id');
    const exit = await ctx.manager.groupModel.findByPk(id);
    if (!exit) {
      throw new NotFound({
        msg: '分组不存在,更新失败'
      });
    }
    exit.name = v.get('body.name');
    exit.info = v.get('body.info');
    exit.save();
  }

2、通过类方法
create increment

return sequelize.transaction(async t => {
static async like(art_id, type, uid) {
        const favor = await Favor.findOne({
            where: {
                art_id,
                type,
                uid
            }
        })
        if (favor) {
            throw new global.errs.LikeError()
        }
        return sequelize.transaction(async t => {
            await Favor.create({
                art_id,
                type,
                uid
            }, {
                transaction: t
            })
            const art = await Art.getData(art_id, type, false)
            await art.increment('fav_nums', {
                by: 1,
                transaction: t
            })
        })
    }
static async addComment(bookID, content){
        const comment = await Comment.findOne({
            where:{
                book_id:bookID,
                content
            }
        })
        if(!comment){
            // 近似
            // 你好酷 你真酷,
            return await Comment.create({
                book_id: bookID,
                content,
                nums:1
            })
        }else{
            return await comment.increment('nums', {
                by: 1
            })
        }
    }

Sequelize 中文API文档-7. Scopes 作用域的使用:

提前定义好 where 条件,然后将这种定义好的条件又可以重新组合

  • 先在define定义:
const sequelize = new Sequelize(dbName,user,password,{
    dialect:'mysql',
    host,
    port,
    logging:true,
  
    timezone: '+08:00',
    define:{
        //create_time  update_time delete_time
        timestamps:true,
        paranoid:true,
        createdAt:'created_at',
        updatedAt:'updated_at',
        deletedAt:'deleted_at',
        underscored:true,
        freezeTableName:true,
        scopes:{
            bh:{
                attributes:{
                    exclude:['updated_at','deleted_at','created_at']
                }
            }
        }
    }
})
  • 后使用:
static async _getListByType(ids, type) {
        let arts = []
        const finder = {
            where: {
                id: {
                    [Op.in]: ids
                }
            }
        }
        const scope = 'bh'
        switch (type) {
            case 100:
                arts = await Movie.scope(scope).findAll(finder)
                break
            case 200:
                arts = await Music.scope(scope).findAll(finder)
                break
            case 300:
                arts = await Sentence.scope(scope).findAll(finder)
            case 400:
                break
            default:
                break
        }
        return arts
    }

查询范围 Scope (预定义查询条件)


sequelize 的op模块:
async searchLogs (v, keyword) {
    const start = v.get('query.page');
    const count1 = v.get('query.count');
    let condition = {};
    v.get('query.name') && set(condition, 'user_name', v.get('query.name'));
    v.get('query.start') &&
      v.get('query.end') &&
      set(condition, 'time', {
        [Sequelize.Op.between]: [v.get('query.start'), v.get('query.end')]
      });
    let { rows, count } = await Log.findAndCountAll({
      where: Object.assign({}, condition, {
        message: {
          [Sequelize.Op.like]: `%${keyword}%`
        }
      }),
      offset: start * count1,
      limit: count1,
      order: [['time', 'DESC']]
    });
    return {
      rows,
      total: count
    };
  }

事务(transaction):
const { db } = require('lin-mizar/lin/db');
async createGroup (ctx, v) {
    const exit = await ctx.manager.groupModel.findOne({
      where: {
        name: v.get('body.name')
      }
    });
    if (exit) {
      throw new Forbidden({
        msg: '分组已存在,不可创建同名分组'
      });
    }
    let transaction;
    try {
      transaction = await db.transaction();
      const group = await ctx.manager.groupModel.create(
        {
          name: v.get('body.name'),
          info: v.get('body.info')
        },
        {
          transaction
        }
      );
      for (const item of v.get('body.auths')) {
        const { auth, module } = findMetaByAuth(item);
        await ctx.manager.authModel.create(
          {
            auth,
            module,
            group_id: group.id
          },
          {
            transaction
          }
        );
      }
      await transaction.commit();
    } catch (err) {
      if (transaction) await transaction.rollback();
    }
    return true;
  }
static async like(art_id, type, uid) {
        const favor = await Favor.findOne({
            where: {
                art_id,
                type,
                uid
            }
        })
        if (favor) {
            throw new global.errs.LikeError()
        }
        return sequelize.transaction(async t => {
            await Favor.create({
                art_id,
                type,
                uid
            }, {
                transaction: t
            })
            const art = await Art.getData(art_id, type, false)
            await art.increment('fav_nums', {
                by: 1,
                transaction: t
            })
        })
    }

    static async disLike(art_id, type, uid) {
        const favor = await Favor.findOne({
            where: {
                art_id,
                type,
                uid
            }
        })
        if (!favor) {
            throw new global.errs.DislikeError()
        }
        // Favor 表 favor 记录
        return sequelize.transaction(async t => {
            await favor.destroy({
                force: true,
                transaction: t
            })
            const art = await Art.getData(art_id, type, false)
            await art.decrement('fav_nums', {
                by: 1,
                transaction: t
            })
        })
    }

相关文章

网友评论

      本文标题:使用Sequelize操作MySQL

      本文链接:https://www.haomeiwen.com/subject/hssusctx.html