zoukankan      html  css  js  c++  java
  • [转]Sequelize 中文API文档-4. 查询与原始查询

    本文转自:https://itbilu.com/nodejs/npm/VJIR1CjMb.html

    Sequelize中有两种查询:使用Model(模型)中的方法查询和使用sequelize.query()进行基于SQL语句的原始查询。

    1. Model查询
    2. 原始查询

    1. Model查询

    Model是一种表示与数据库中表关系的描述对象,它通过sequlize.define方法定义或通过sequlize.import导入创建实例对象。通过Model进行进行数据查询时,我们可以实现类似在数据库中直接使用SQL语句的查询、排序、分组、别名、连接查询等。

    1.1 Attributes - 属性与查询字段

    查询时,如果只需要查询模型的部分属性,可以在通过在查询选项中指定attributes实现。该选项是一个数组参数,在数组中指定要查询的属性即可,这些要查询的属性就表示要在数据库查询的字段:

    Model.findAll({
      attributes: ['foo', 'bar']
    });
    SELECT foo, bar ...

    查询属性(字段)可以通过传入一个嵌套数据进行重命名:

    Model.findAll({
      attributes: ['foo', ['bar', 'baz']]
    });
    SELECT foo, bar AS baz ...

    通过sequelize.fn方法可以进行聚合查询:

    Model.findAll({
      attributes: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
    });
    SELECT COUNT(hats) AS no_hats ...

    在使用聚合函数时,要给聚合字段指定一个别名。如,在上例中我们为聚合函数指定了别名'no_hats',这样我们就能在查询的回调函数实例中通过instance.get('no_hats')来访问聚合统计的结果。

    当需要查询所有字段并对某一字段使用聚合查询时,而只需要以对象的形式传入attributes并添加include子属性即可。

    // 拽定全查询字段比较麻烦
    Model.findAll({
      attributes: ['id', 'foo', 'bar', 'baz', 'quz', [sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
    });
    
    // 这样会比较简短,且在你添加/删除属性后不会出错
    Model.findAll({
      attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']] }
    });
    SELECT id, foo, bar, baz, quz, COUNT(hats) AS no_hats ...

    全部查询时,可以通过exclude子属性来排除不需要查询的字段:

    Model.findAll({
      attributes: { exclude: ['baz'] }
    });
    SELECT id, foo, bar, quz ...

    关于聚合查询,请参考:在Sequelize中使用group by分组聚合查询

    1.2 Where - 指定筛选条件

    在模型的 find/finAll 或 updates/destroys 操作中,可以指定一个where选项以指定筛选条件,

    where是一个包含属性/值对对象,sequelize会根据此对象生产查询语句的筛选条件。

    基本用法

    Post.findAll({
      where: {
        authorId: 2
      }
    });
    // SELECT * FROM post WHERE authorId = 2
    
    Post.findAll({
      where: {
        authorId: 12,
        status: 'active'
      }
    });
    // SELECT * FROM post WHERE authorId = 12 AND status = 'active';
    
    Post.destroy({
      where: {
        status: 'inactive'
      }
    });
    // DELETE FROM post WHERE status = 'inactive';
    
    Post.update({
      updatedAt: null,
    }, {
      where: {
        deletedAt: {
          $ne: null
        }
      }
    });
    // UPDATE post SET updatedAt = null WHERE deletedAt NOT NULL;
    
    Post.findAll({
      where: sequelize.where(sequelize.fn('char_length', sequelize.col('status')), 6)
    });
    // SELECT * FROM post WHERE char_length(status) = 6;

    操作符

    $and: {a: 5}           // AND (a = 5)
    $or: [{a: 5}, {a: 6}]  // (a = 5 OR a = 6)
    $gt: 6,                // > 6
    $gte: 6,               // >= 6
    $lt: 10,               // < 10
    $lte: 10,              // <= 10
    $ne: 20,               // != 20
    $not: true,            // IS NOT TRUE
    $between: [6, 10],     // BETWEEN 6 AND 10
    $notBetween: [11, 15], // NOT BETWEEN 11 AND 15
    $in: [1, 2],           // IN [1, 2]
    $notIn: [1, 2],        // NOT IN [1, 2]
    $like: '%hat',         // LIKE '%hat'
    $notLike: '%hat'       // NOT LIKE '%hat'
    $iLike: '%hat'         // ILIKE '%hat' (case insensitive) (PG only)
    $notILike: '%hat'      // NOT ILIKE '%hat'  (PG only)
    $like: { $any: ['cat', 'hat']}
                           // LIKE ANY ARRAY['cat', 'hat'] - also works for iLike and notLike
    $overlap: [1, 2]       // && [1, 2] (PG array overlap operator)
    $contains: [1, 2]      // @> [1, 2] (PG array contains operator)
    $contained: [1, 2]     // <@ [1, 2] (PG array contained by operator)
    $any: [2,3]            // ANY ARRAY[2, 3]::INTEGER (PG only)
    
    $col: 'user.organization_id' // = "user"."organization_id", with dialect specific column identifiers, PG in this example

    组合查询

    {
      rank: {
        $or: {
          $lt: 1000,
          $eq: null
        }
      }
    }
    // rank < 1000 OR rank IS NULL
    
    {
      createdAt: {
        $lt: new Date(),
        $gt: new Date(new Date() - 24 * 60 * 60 * 1000)
      }
    }
    // createdAt < [timestamp] AND createdAt > [timestamp]
    
    {
      $or: [
        {
          title: {
            $like: 'Boat%'
          }
        },
        {
          description: {
            $like: '%boat%'
          }
        }
      ]
    }
    // title LIKE 'Boat%' OR description LIKE '%boat%'

    嵌套对象

    {
      meta: {
        video: {
          url: {
            $ne: null
          }
        }
      }
    }

    嵌套键

    {
      "meta.audio.length": {
        $gt: 20
      }
    }

    包含

    {
      "meta": {
        $contains: {
          site: {
            url: 'http://itbilu.com'
          }
        }
      }
    }

    关系/联合

    // 查询所有至少有一个task的projects,task.state === project.task
    Project.findAll({
        include: [{
            model: Task,
            where: { state: Sequelize.col('project.state') }
        }]
    })

    1.3 limit/offset - 分页与限制返回结果数

    查询进,我们可以使用limit限制返回结果条数,并可以通过offset来设置查询偏移(跳过)量,通过这两个属性我们可以实现分页查询的功能:

    // 获取 10 条数据(实例)
    Project.findAll({ limit: 10 })
    
    // 跳过 8 条数据(实例)
    Project.findAll({ offset: 8 })
    
    // 跳过 5 条数据并获取其后的 5 条数据(实例)
    Project.findAll({ offset: 5, limit: 5 })

    1.4 查询排序

    order选项用于查询结果的排序数据。排序时应该传入一个包含属性-排序方向的元组/数组,以保证正确的转义:

    something.findOne({
      order: [
        // 转义 username 并对查询结果按 DESC 方向排序
        ['username', 'DESC'],
    
        // 按 max(age) 排序
        sequelize.fn('max', sequelize.col('age')),
    
        // 按 max(age) DESC 排序
        [sequelize.fn('max', sequelize.col('age')), 'DESC'],
    
        // 按 otherfunction(`col1`, 12, 'lalala') DESC 排序
        [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
    
        // 按相关联的User 模型的 name 属性排序
        [User, 'name', 'DESC'],
    
        // 按相关联的User 模型的 name 属性排序并将模型起别名为 Friend
        [{model: User, as: 'Friend'}, 'name', 'DESC'],
    
        // 按相关联的User 模型的嵌套关联的 Company 模型的 name 属性排序
        [User, Company, 'name', 'DESC'],
      ]
      // 以下所有声明方式都会视为字面量,应该小心使用
      order: 'convert(user_name using gbk)'
      order: 'username DESC'
      order: sequelize.literal('convert(user_name using gbk)')
    })

    2. 原始查询

    有时会使用原始查询或执行已准备好的SQL语句,这时可以用Sequlize提供的工具函数sequelize.query来实现。

    2.1 原始查询方法

    默认情况下,该函数会返回两个参数 - 一个包含结果的数组和一个包含原数据对象。请注意,由于是原始查询,所以返回的元数据与使用的数据库类型有关,其对元数据的处理并不一致。

    sequelize.query("UPDATE users SET y = 42 WHERE x = 12").spread(function(results, metadata) {
      // Results 会是一个空数组和一个包含受影响行数的metadata 元数据对象
    })

    如果不想使用元数据,可以查询时指定表示查询类型的type参数,以告诉sequelize 应该怎样去格式化返回结果。

    sequelize.query("SELECT * FROM `users`", { type: sequelize.QueryTypes.SELECT})
      .then(function(users) {
        // 并不需要在这spread 展开结果,因为所返回的只有所查询的结果
      })

    在选项参数中,可以使用model参数指定一个模型,指定后会将查询结果会是传入模型的实例:

    // 调用已定义的模型并对其创建实例
    sequelize.query('SELECT * FROM projects', { model: Projects }).then(function(projects){
      // 每条记录都是一个Project 实例
    })

    2.2 查询参数替换

    原始查询中有两种替换查询参数的方法,以:开头的参数的形式替换或以不命名以?替换。在选项对象中传递参数:

    • 如果传递一个数组,? 会按数组的顺序被依次替换
    • 巢传递一个对象,:key将会用对象的键替换。如果对象中未找到指定键,则会引发异常(反之亦然)
    sequelize.query('SELECT * FROM projects WHERE status = ?',
      { replacements: ['active'], type: sequelize.QueryTypes.SELECT }
    ).then(function(projects) {
      console.log(projects)
    })
    
    sequelize.query('SELECT * FROM projects WHERE status = :status ',
      { replacements: { status: 'active' }, type: sequelize.QueryTypes.SELECT }
    ).then(function(projects) {
      console.log(projects)
    })

    2.3 参数绑定

    参数绑定类似于参数替换。尤其是参数替换会在发送到数据库前被sequelize转义和替换,而参数绑定会被发送到SQL 查询文本外。

    只有SQLite 和 PostgreSQL支持参数绑定,其它类型数据库都会将其插入到SQL 查询,并以相同的方式进行参数替换。参数绑定可以使用$1、$2……或$key的形式:

    • 如果传入的是数组,$1会绑定到数组听第1个参数 (bind[0])
    • 如果传入一个对象,$key会绑定到object['key']。每个key 必须以非数字的字符开始。$1不是个有效的key,尽管object['1'] 是存在的。
    • 在使用$$时,不会被转义而是将$做为一个字面量使用。

    传入的数组或对象必须包含所有绑定值,否则Sequelize会抛出异常。这同样适用于数据库可能会忽略绑定参数的情况下。

    数据库可能会做进一步限制,绑定参数不能使用数据库关键字,也不能是表或列名,它在引用文本或数据时也可能被忽略。在PostgreSQL中,如果不能从上下文$1::varchar中推断类型,那么也需要进行类型转换。

    sequelize.query('SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $1',
      { bind: ['active'], type: sequelize.QueryTypes.SELECT }
    ).then(function(projects) {
      console.log(projects)
    })
    
    sequelize.query('SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $status',
      { bind: { status: 'active' }, type: sequelize.QueryTypes.SELECT }
    ).then(function(projects) {
      console.log(projects)
    })
  • 相关阅读:
    [rabbitmq] python版本(二) 工作队列
    [rabbitmq] python版本(一)HelloWorld
    rabbitmq安装上手
    leetcode1 两数之和
    mybatis学习笔记(一)入门上手
    神经网络简介
    hexo+github pages搭建个人博客
    简单RTSCamera实现
    数据结构复习:树
    LINQ
  • 原文地址:https://www.cnblogs.com/freeliver54/p/10195987.html
Copyright © 2011-2022 走看看