美文网首页web全栈
Sequelize V5.9.4 MVC模式(七 | 细节补充)

Sequelize V5.9.4 MVC模式(七 | 细节补充)

作者: 亿汇学_江湖老师 | 来源:发表于2019-07-12 18:36 被阅读0次

    大家可以前往 Sequelize中文文档,查看 Sequelize不同版本【5.x、4.x】的文档

    本文档分多个篇章,难易程度从低到高,学习此篇章之前,务必确保自己已经掌握 node.jsexpress、es6语法、mysql等关系型数据库的sql语法等

    细节补充

    数据检索/查找器

    findByPk

    // 搜索已知的ids
    Project.findByPk(123).then(project => {
      // project 将是 Project的一个实例,并具有在表中存为 id 123 条目的内容.
      // 如果没有定义这样的条目,你将获得null
    })
    

    findOrCreate:搜索特定元素或创建它(如果不可用)

    User
      .findOrCreate({where: {username: 'Mjhu'}, defaults: {job: 'Technical Lead JavaScript'}})
      . then(([user, created]) => {
        console.log(user.get({
          plain: true
        }))
        console.log(created)
    
        /*
        findOrCreate 返回一个包含已找到或创建的对象的数组,找到或创建的对象和一个布尔值,如果创建一个新对象将为true,否则为false,像这样:
    
        [ {
            username: 'Mjhu',
            job: 'Technical Lead JavaScript',
            id: 1,
            createdAt: '2019-07-12T10:45:46.000Z'
            updatedAt: '2019-07-12T10:45:46.000Z'
          },
          true ]
    
    在上面的例子中,第三行的数组将分成2部分,并将它们作为参数传递给回调函数,在这种情况下将它们视为 "user" 和 "created" .(所以“user”将是返回数组的索引0的对象,并且 "created" 将等于 "true".)
        */
      })
    

    排除指定的字段

    Model.findAll({
      attributes: { exclude: ['createdAt','updatedAt'] } //除了排除的这两个字段,其他字段都返回
    });
    
    运算符安全性

    默认情况下,Sequelize 将使用 Symbol 运算符. 使用没有任何别名的 Sequelize 可以提高安全性.没有任何字符串别名将使得运算符可能被注入的可能性降到极低,但你应该始终正确验证和清理用户输入.

    一些框架会自动将用户输入解析为js对象,如果你无法清理输入,则可能会将带有字符串运算符的 Object 注入Sequelize.

    为了更好的安全性,强烈建议在代码中使用 Sequelize.Op 中的符号运算符,如Op.and / Op.or,而不依赖于任何基于字符串的运算符,如 $and / $or. 你可以通过设置 operatorsAliases 参数来限制应用程序所需的别名,记住清理用户输入,特别是当你直接将它们传递给 Sequelize 方法时.

    const Op = Sequelize.Op;
    
    // 不用任何操作符别名使用 sequelize 
    const connection = new Sequelize(db, user, pass, { operatorsAliases: false });
    
    // 只用 $and => Op.and 操作符别名使用 sequelize 
    const connection2 = new Sequelize(db, user, pass, { operatorsAliases: { $and: Op.and } });
    
    排序
    Subtask.findAll({
      order: [
        // 将转义标题,并根据有效的方向参数列表验证DESC
        ['title', 'DESC'],
    
        // 将按最大值排序(age)
        sequelize.fn('max', sequelize.col('age')),
    
        // 将按最大顺序(age) DESC
        [sequelize.fn('max', sequelize.col('age')), 'DESC'],
    
        // 将按 otherfunction 排序(`col1`, 12, 'lalala') DESC
        [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
    
        // 将使用模型名称作为关联的名称排序关联模型的 created_at.
        [Task, 'createdAt', 'DESC'],
    
        // Will order through an associated model's created_at using the model names as the associations' names.
        [Task, Project, 'createdAt', 'DESC'],
    
        // 将使用关联的名称由关联模型的created_at排序.
        ['Task', 'createdAt', 'DESC'],
    
        // Will order by a nested associated model's created_at using the names of the associations.
        ['Task', 'Project', 'createdAt', 'DESC'],
    
        // Will order by an associated model's created_at using an association object. (优选方法)
        [Subtask.associations.Task, 'createdAt', 'DESC'],
    
        // Will order by a nested associated model's created_at using association objects. (优选方法)
        [Subtask.associations.Task, Task.associations.Project, 'createdAt', 'DESC'],
    
        // Will order by an associated model's created_at using a simple association object.
        [{model: Task, as: 'Task'}, 'createdAt', 'DESC'],
    
        // 嵌套关联模型的 created_at 简单关联对象排序
        [{model: Task, as: 'Task'}, {model: Project, as: 'Project'}, 'createdAt', 'DESC']
      ]
      
      // 将按年龄最大值降序排列
      order: sequelize.literal('max(age) DESC')
    
      // 按最年龄大值升序排列,当省略排序条件时默认是升序排列
      order: sequelize.fn('max', sequelize.col('age'))
    
      // 按升序排列是省略排序条件的默认顺序
      order: sequelize.col('age')
      
      // 将根据方言随机排序 (而不是 fn('RAND') 或 fn('RANDOM'))
      order: sequelize.random()
    })
    
    原始查询

    有时候,你可能会期待一个你想要显示的大量数据集,而无需操作. 对于你选择的每一行,Sequelize 创建一个具有更新,删除和获取关联等功能的实例.如果你有数千行,则可能需要一些时间. 如果你只需要原始数据,并且不想更新任何内容,你可以这样做来获取原始数据.

    // 你期望从数据库的一个巨大的数据集,
    // 并且不想花时间为每个条目构建DAO?
    // 你可以传递一个额外的查询参数来取代原始数据:
    Project.findAll({ where: { ... }, raw: true })
    

    count - 计算数据库中元素的出现次数

    //这里是获取属性的最大值的方法:
    /*
       我们假设3个具有属性年龄的对象.
       第一个是10岁,
       第二个是5岁,
       第三个是40岁.
    */
    Project.max('age').then(max => {
      // 将返回 40
    })
    
    Project.max('age', { where: { age: { [Op.lt]: 20 } } }).then(max => {
      // 将会是 10
    })
    

    min - 获取特定表中特定属性的最小值

    这里是获取属性的最小值的方法:

    /*
       我们假设3个具有属性年龄的对象.
       第一个是10岁,
       第二个是5岁,
       第三个是40岁.
    */
    Project.min('age').then(min => {
      // 将返回 5
    })
    
    Project.min('age', { where: { age: { [Op.gt]: 5 } } }).then(min => {
      // 将会是 10
    })
    

    sum - 特定属性的值求和

    为了计算表的特定列的总和,可以使用sum方法.

    /*
       我们假设3个具有属性年龄的对象.
       第一个是10岁,
       第二个是5岁,
       第三个是40岁.
    */
    Project.sum('age').then(sum => {
      // 将返回 55
    })
    
    Project.sum('age', { where: { age: { [Op.gt]: 5 } } }).then(sum => {
      // 将会是 50
    })
    
    排序预加载关联

    在一对多关系的情况下.

    Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] });
    Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] });
    Company.findAll({
      include: [ { model: Division, as: 'Div' } ],
      order: [ [ { model: Division, as: 'Div' }, 'name' ] ]
    });
    Company.findAll({
      include: [ { model: Division, as: 'Div' } ],
      order: [ [ { model: Division, as: 'Div' }, 'name', 'DESC' ] ]
    });
    Company.findAll({
      include: [ { model: Division, include: [ Department ] } ],
      order: [ [ Division, Department, 'name' ] ]
    });
    

    在多对多关系的情况下,你还可以通过表中的属性进行排序.

    Company.findAll({
      include: [ { model: Division, include: [ Department ] } ],
      order: [ [ Division, DepartmentDivision, 'name' ] ]
    });
    
    嵌套预加载

    你可以使用嵌套的预加载来加载相关模型的所有相关模型:

    User.findAll({
      include: [
        {model: Tool, as: 'Instruments', include: [
          {model: Teacher, include: [ /* etc */]}
        ]}
      ]
    }).then(users => {
      console.log(JSON.stringify(users))
    
      /*
        [{
          "name": "John Doe",
          "id": 1,
          "createdAt": "2013-03-20T20:31:45.000Z",
          "updatedAt": "2013-03-20T20:31:45.000Z",
          "Instruments": [{ // 1:M and N:M association
            "name": "Toothpick",
            "id": 1,
            "createdAt": null,
            "updatedAt": null,
            "userId": 1,
            "Teacher": { // 1:1 association
              "name": "Jimi Hendrix"
            }
          }]
        }]
      */
    })
    

    这将产生一个外连接. 但是,相关模型上的 where 语句将创建一个内部连接,并仅返回具有匹配子模型的实例. 要返回所有父实例,你应该添加 required: false.

    User.findAll({
      include: [{
        model: Tool,
        as: 'Instruments',
        include: [{
          model: Teacher,
          where: {
            school: "Woodstock Music School"
          },
          required: false
        }]
      }]
    }).then(users => {
      /* ... */
    })
    

    以上查询将返回所有用户及其所有乐器,但只会返回与 Woodstock Music School 相关的老师.
    包括所有也支持嵌套加载:

    User.findAll({ include: [{ all: true, nested: true }]});
    

    到这里, Sequelize V5.9.4 的大部分常用的知识就介绍完毕了。更多细节请前往 Sequelize 中文文档

    相关文章

      网友评论

        本文标题:Sequelize V5.9.4 MVC模式(七 | 细节补充)

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