Sequelize 中文文檔 v4 - Querying - 查詢

Querying - 查詢

此係列文章的應用示例已發佈於 GitHub: sequelize-docs-Zh-CN. 能夠 Fork 幫助改進或 Star 關注更新. 歡迎 Star.html

屬性

想要只選擇某些屬性,可使用 attributes 選項。 一般是傳遞一個數組:git

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

屬性可使用嵌套數組來重命名:github

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 ...

使用聚合功能時,必須給它一個別名,以便可以從模型中訪問它。 在上面的例子中,您可使用 instance.get('no_hats') 得到帽子數量。sql

有時,若是您只想添加聚合,則列出模型的全部屬性可能使人厭煩:數據庫

// This is a tiresome way of getting the number of hats...
Model.findAll({
  attributes: ['id', 'foo', 'bar', 'baz', 'quz', [sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
});

// This is shorter, and less error prone because it still works if you add / remove attributes
Model.findAll({
  attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']] }
});
SELECT id, foo, bar, baz, quz, COUNT(hats) AS no_hats ...

一樣,它也能夠刪除一些指定的屬性:數組

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

Where

不管您是經過 findAll/find 或批量 updates/destroys 進行查詢,均可以傳遞一個 where 對象來過濾查詢。安全

where 一般用 attribute:value 鍵值對獲取一個對象,其中 value 能夠是匹配等式的數據或其餘運算符的鍵值對象。框架

也能夠經過嵌套 orand 運算符 的集合來生成複雜的 AND/OR 條件。less

基礎

const Op = Sequelize.Op;

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: {
      [Op.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;

操做符

Sequelize 可用於建立更復雜比較的符號運算符 -

const Op = Sequelize.Op

[Op.and]: {a: 5}           // 且 (a = 5)
[Op.or]: [{a: 5}, {a: 6}]  // (a = 5 或 a = 6)
[Op.gt]: 6,                // id > 6
[Op.gte]: 6,               // id >= 6
[Op.lt]: 10,               // id < 10
[Op.lte]: 10,              // id <= 10
[Op.ne]: 20,               // id != 20
[Op.eq]: 3,                // = 3
[Op.not]: true,            // 不是 TRUE
[Op.between]: [6, 10],     // 在 6 和 10 之間
[Op.notBetween]: [11, 15], // 不在 11 和 15 之間
[Op.in]: [1, 2],           // 在 [1, 2] 之中
[Op.notIn]: [1, 2],        // 不在 [1, 2] 之中
[Op.like]: '%hat',         // 包含 '%hat'
[Op.notLike]: '%hat'       // 不包含 '%hat'
[Op.iLike]: '%hat'         // 包含 '%hat' (不區分大小寫)  (僅限 PG)
[Op.notILike]: '%hat'      // 不包含 '%hat'  (僅限 PG)
[Op.regexp]: '^[h|a|t]'    // 匹配正則表達式/~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正則表達式/!~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]'    // ~* '^[h|a|t]' (僅限 PG)
[Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (僅限 PG)
[Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何數組['cat', 'hat'] - 一樣適用於 iLike 和 notLike
[Op.overlap]: [1, 2]       // && [1, 2] (PG數組重疊運算符)
[Op.contains]: [1, 2]      // @> [1, 2] (PG數組包含運算符)
[Op.contained]: [1, 2]     // <@ [1, 2] (PG數組包含於運算符)
[Op.any]: [2,3]            // 任何數組[2, 3]::INTEGER (僅限PG)

[Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用數據庫語言特定的列標識符, 本例使用 PG

範圍選項

全部操做符都支持支持的範圍類型查詢。

請記住,提供的範圍值也能夠定義綁定的 inclusion/exclusion

// 全部上述相等和不相等的操做符加上如下內容:

[Op.contains]: 2           // @> '2'::integer (PG range contains element operator)
[Op.contains]: [1, 2]      // @> [1, 2) (PG range contains range operator)
[Op.contained]: [1, 2]     // <@ [1, 2) (PG range is contained by operator)
[Op.overlap]: [1, 2]       // && [1, 2) (PG range overlap (have points in common) operator)
[Op.adjacent]: [1, 2]      // -|- [1, 2) (PG range is adjacent to operator)
[Op.strictLeft]: [1, 2]    // << [1, 2) (PG range strictly left of operator)
[Op.strictRight]: [1, 2]   // >> [1, 2) (PG range strictly right of operator)
[Op.noExtendRight]: [1, 2] // &< [1, 2) (PG range does not extend to the right of operator)
[Op.noExtendLeft]: [1, 2]  // &> [1, 2) (PG range does not extend to the left of operator)

組合

{
  rank: {
    [Op.or]: {
      [Op.lt]: 1000,
      [Op.eq]: null
    }
  }
}
// rank < 1000 OR rank IS NULL

{
  createdAt: {
    [Op.lt]: new Date(),
    [Op.gt]: new Date(new Date() - 24 * 60 * 60 * 1000)
  }
}
// createdAt < [timestamp] AND createdAt > [timestamp]

{
  [Op.or]: [
    {
      title: {
        [Op.like]: 'Boat%'
      }
    },
    {
      description: {
        [Op.like]: '%boat%'
      }
    }
  ]
}
// title LIKE 'Boat%' OR description LIKE '%boat%'

運算符別名

Sequelize 容許將特定字符串設置爲操做符的別名 -

const Op = Sequelize.Op;
const operatorsAliases = {
  $gt: Op.gt
}
const connection = new Sequelize(db, user, pass, { operatorsAliases })

[Op.gt]: 6 // > 6
$gt: 6 // 等同於使用 Op.gt (> 6)

運算符安全性

使用沒有任何別名的 Sequelize 能夠提升安全性。

一些框架會自動將用戶輸入解析爲js對象,若是您沒法清理輸入,則可能會將具備字符串運算符的對象注入到 Sequelize。

不帶任何字符串別名將使運算符不太可能被注入,但您應該始終正確驗證和清理用戶輸入。

因爲向後兼容性緣由Sequelize默認設置如下別名 -

$eq, $ne, $gte, $gt, $lte, $lt, $not, $in, $notIn, $is, $like, $notLike, $iLike, $notILike, $regexp, $notRegexp, $iRegexp, $notIRegexp, $between, $notBetween, $overlap, $contains, $contained, $adjacent, $strictLeft, $strictRight, $noExtendRight, $noExtendLeft, $and, $or, $any, $all, $values, $col

目前,如下遺留別名也被設置,但計劃在不久的未來徹底刪除 -

ne, not, in, notIn, gte, gt, lte, lt, like, ilike, $ilike, nlike, $notlike, notilike, .., between, !.., notbetween, nbetween, overlap, &&, @>, <@

爲了更好的安全性,建議使用 Sequelize.Op,而不是依賴任何字符串別名。 您能夠經過設置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 } });

若是你使用默認別名而且不限制它們,Sequelize會發出警告。若是您想繼續使用全部默認別名(不包括舊版別名)而不發出警告,您能夠傳遞如下運算符參數 -

const Op = Sequelize.Op;
const operatorsAliases = {
  $eq: Op.eq,
  $ne: Op.ne,
  $gte: Op.gte,
  $gt: Op.gt,
  $lte: Op.lte,
  $lt: Op.lt,
  $not: Op.not,
  $in: Op.in,
  $notIn: Op.notIn,
  $is: Op.is,
  $like: Op.like,
  $notLike: Op.notLike,
  $iLike: Op.iLike,
  $notILike: Op.notILike,
  $regexp: Op.regexp,
  $notRegexp: Op.notRegexp,
  $iRegexp: Op.iRegexp,
  $notIRegexp: Op.notIRegexp,
  $between: Op.between,
  $notBetween: Op.notBetween,
  $overlap: Op.overlap,
  $contains: Op.contains,
  $contained: Op.contained,
  $adjacent: Op.adjacent,
  $strictLeft: Op.strictLeft,
  $strictRight: Op.strictRight,
  $noExtendRight: Op.noExtendRight,
  $noExtendLeft: Op.noExtendLeft,
  $and: Op.and,
  $or: Op.or,
  $any: Op.any,
  $all: Op.all,
  $values: Op.values,
  $col: Op.col
};

const connection = new Sequelize(db, user, pass, { operatorsAliases });

JSONB

JSONB 能夠以三種不一樣的方式進行查詢。

嵌套對象

{
  meta: {
    video: {
      url: {
        [Op.ne]: null
      }
    }
  }
}

嵌套鍵

{
  "meta.audio.length": {
    [Op.gt]: 20
  }
}

外包裹

{
  "meta": {
    [Op.contains]: {
      site: {
        url: 'http://google.com'
      }
    }
  }
}

關係 / 關聯

// 找到全部具備至少一個 task 的  project,其中 task.state === project.state
Project.findAll({
    include: [{
        model: Task,
        where: { state: Sequelize.col('project.state') }
    }]
})

分頁 / 限制

// 獲取10個實例/行
Project.findAll({ limit: 10 })

// 跳過8個實例/行
Project.findAll({ offset: 8 })

// 跳過5個實例,而後取5個
Project.findAll({ offset: 5, limit: 5 })

排序

order 須要一個條目的數組來排序查詢或者一個 sequelize 方法。通常來講,你將要使用任一屬性的 tuple/array,並肯定排序的正反方向。

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')
})

若是這篇文章對您有幫助, 感謝 下方點贊 或 Star GitHub: sequelize-docs-Zh-CN 支持, 謝謝.

相關文章
相關標籤/搜索