Sequelize官方中文文檔 4. Querying - 查詢

Sequelize官方GitHub:https://github.com/sequelize/sequelize
Sequelize官方中文文檔:https://github.com/demopark/sequelize-docs-Zh-CN
Sequelize官方英文文檔:http://docs.sequelizejs.com/

Querying - 查詢

屬性

想要只選擇某些屬性,可以使用 attributes 選項(xiàng)缴允。 通常是傳遞一個(gè)數(shù)組:

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

SELECT foo, bar ...

屬性可以使用嵌套數(shù)組來重命名:

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

SELECT foo, bar AS baz ...

也可以使用 sequelize.fn 來進(jìn)行聚合:

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

SELECT COUNT(hats) AS no_hats ...

使用聚合功能時(shí),必須給它一個(gè)別名,以便能夠從模型中訪問它舆吮。 在上面的例子中袜啃,您可以使用 instance.get('no_hats') 獲得帽子數(shù)量囊陡。

有時(shí),如果您只想添加聚合葱她,則列出模型的所有屬性可能令人厭煩:

// 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 進(jìn)行查詢似扔,都可以傳遞一個(gè) where 對象來過濾查詢吨些。

where 通常用 attribute:value 鍵值對獲取一個(gè)對象,其中 value 可以是匹配等式的數(shù)據(jù)或其他運(yùn)算符的鍵值對象虫几。

也可以通過嵌套 orand 運(yùn)算符 的集合來生成復(fù)雜的 AND/OR 條件锤灿。

基礎(chǔ)

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.findAll({
  where: {
    [Op.or]: [{authorId: 12}, {authorId: 13}]
  }
});
// SELECT * FROM post WHERE authorId = 12 OR authorId = 13;

Post.findAll({
  where: {
    authorId: {
      [Op.or]: [12, 13]
    }
  }
});
// SELECT * FROM post WHERE authorId = 12 OR authorId = 13;

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 可用于創(chuàng)建更復(fù)雜比較的符號(hào)運(yùn)算符 -

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' (不區(qū)分大小寫)  (僅限 PG)
[Op.notILike]: '%hat'      // 不包含 '%hat'  (僅限 PG)
[Op.regexp]: '^[h|a|t]'    // 匹配正則表達(dá)式/~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正則表達(dá)式/!~ '^[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']} // 包含任何數(shù)組['cat', 'hat'] - 同樣適用于 iLike 和 notLike
[Op.overlap]: [1, 2]       // && [1, 2] (PG數(shù)組重疊運(yùn)算符)
[Op.contains]: [1, 2]      // @> [1, 2] (PG數(shù)組包含運(yùn)算符)
[Op.contained]: [1, 2]     // <@ [1, 2] (PG數(shù)組包含于運(yùn)算符)
[Op.any]: [2,3]            // 任何數(shù)組[2, 3]::INTEGER (僅限PG)

[Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用數(shù)據(jù)庫語言特定的列標(biāo)識(shí)符, 本例使用 PG

范圍選項(xiàng)

所有操作符都支持支持的范圍類型查詢。

請記住辆脸,提供的范圍值也可以定義綁定的 inclusion/exclusion但校。

// 所有上述相等和不相等的操作符加上以下內(nèi)容:

[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%'

運(yùn)算符別名

Sequelize 允許將特定字符串設(shè)置為操作符的別名 -

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)

運(yùn)算符安全性

使用沒有別名的 Sequelize 可以提高安全性。
有些框架會(huì)自動(dòng)將用戶輸入解析為 js 對象啡氢,如果您不能清理輸入的內(nèi)容状囱,則可能會(huì)將具有字符串運(yùn)算符的 Object 注入 Sequelize术裸。

沒有任何字符串別名將使得運(yùn)算符可能被注入的可能性降到極低,但您應(yīng)該始終正確驗(yàn)證和清理用戶輸入亭枷。

為了更好的安全性袭艺,強(qiáng)烈建議在代碼中使用 Sequelize.Op 中的符號(hào)運(yùn)算符,而不是依賴任何字符串別名叨粘。 您可以通過設(shè)置 operatorsAliases 選項(xiàng)來限制應(yīng)用程序需要的別名猾编,請記住要清理用戶輸入,特別是當(dāng)您直接將它們傳遞給 Sequelize 方法時(shí)升敲。

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

如果你使用默認(rèn)別名并且不限制它們答倡,Sequelize會(huì)發(fā)出警告。如果您想繼續(xù)使用所有默認(rèn)別名(不包括舊版別名)而不發(fā)出警告驴党,您可以傳遞以下運(yùn)算符參數(shù) -

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

JSON

JSON 數(shù)據(jù)類型僅由 PostgreSQL瘪撇,SQLite 和 MySQL 語言支持。

PostgreSQL

PostgreSQL 中的 JSON 數(shù)據(jù)類型將值存儲(chǔ)為純文本港庄,而不是二進(jìn)制表示倔既。 如果您只是想存儲(chǔ)和檢索 JSON 格式數(shù)據(jù),那么使用 JSON 將占用更少的磁盤空間鹏氧,并且從其輸入數(shù)據(jù)中構(gòu)建時(shí)間更少渤涌。 但是,如果您想對 JSON 值執(zhí)行任何操作度帮,則應(yīng)該使用下面描述的 JSONB 數(shù)據(jù)類型歼捏。

MSSQL

MSSQL 沒有 JSON 數(shù)據(jù)類型,但是它確實(shí)提供了對于自 SQL Server 2016 以來通過某些函數(shù)存儲(chǔ)為字符串的 JSON 的支持笨篷。使用這些函數(shù)瞳秽,您將能夠查詢存儲(chǔ)在字符串中的 JSON,但是任何返回的值將需要分別進(jìn)行解析率翅。

// ISJSON - 測試一個(gè)字符串是否包含有效的 JSON
User.findAll({
  where: sequelize.where(sequelize.fn('ISJSON', sequelize.col('userDetails')), 1)
})

// JSON_VALUE - 從 JSON 字符串提取標(biāo)量值
User.findAll({
  attributes: [[ sequelize.fn('JSON_VALUE', sequelize.col('userDetails'), '$.address.Line1'), 'address line 1']]
})

// JSON_VALUE - 從 JSON 字符串中查詢標(biāo)量值
User.findAll({
  where: sequelize.where(sequelize.fn('JSON_VALUE', sequelize.col('userDetails'), '$.address.Line1'), '14, Foo Street')
})

// JSON_QUERY - 提取一個(gè)對象或數(shù)組
User.findAll({
  attributes: [[ sequelize.fn('JSON_QUERY', sequelize.col('userDetails'), '$.address'), 'full address']]
})

JSONB

JSONB 可以以三種不同的方式進(jìn)行查詢练俐。

嵌套對象

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

嵌套鍵

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

外包裹

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

關(guān)系 / 關(guān)聯(lián)

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

分頁 / 限制

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

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

// 跳過5個(gè)實(shí)例冕臭,然后取5個(gè)
Project.findAll({ offset: 5, limit: 5 })

排序

order 需要一個(gè)條目的數(shù)組來排序查詢或者一個(gè) sequelize 方法腺晾。一般來說,你將要使用任一屬性的 tuple/array辜贵,并確定排序的正反方向悯蝉。

Subtask.findAll({
  order: [
    // 將轉(zhuǎn)義標(biāo)題,并根據(jù)有效的方向參數(shù)列表驗(yàn)證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'],

    // 將使用模型名稱作為關(guān)聯(lián)的名稱排序關(guān)聯(lián)模型的 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'],

    // 將使用關(guān)聯(lián)的名稱由關(guān)聯(lián)模型的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. (優(yōu)選方法)
    [Subtask.associations.Task, 'createdAt', 'DESC'],

    // Will order by a nested associated model's created_at using association objects. (優(yōu)選方法)
    [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'],

    // 嵌套關(guān)聯(lián)模型的 created_at 簡單關(guān)聯(lián)對象排序
    [{model: Task, as: 'Task'}, {model: Project, as: 'Project'}, 'createdAt', 'DESC']
  ]

  // 將按年齡最大值降序排列
  order: sequelize.literal('max(age) DESC')

  // 按最年齡大值升序排列,當(dāng)省略排序條件時(shí)默認(rèn)是升序排列
  order: sequelize.fn('max', sequelize.col('age'))

  // 按升序排列是省略排序條件的默認(rèn)順序
  order: sequelize.col('age')

  // 將根據(jù)方言隨機(jī)排序 (而不是 fn('RAND') 或 fn('RANDOM'))
  order: sequelize.random()
})

Table Hint

當(dāng)使用 mssql 時(shí),可以使用 tableHint 來選擇傳遞一個(gè)表提示蕉世。 該提示必須是來自 Sequelize.TableHints 的值蔼紧,只能在絕對必要時(shí)使用。 每個(gè)查詢當(dāng)前僅支持單個(gè)表提示狠轻。

表提示通過指定某些選項(xiàng)來覆蓋 mssql 查詢優(yōu)化器的默認(rèn)行為奸例。 它們只影響該子句中引用的表或視圖。

const TableHints = Sequelize.TableHints;

Project.findAll({
  // 添加 table hint NOLOCK
  tableHint: TableHints.NOLOCK
  // 這將生成 SQL 'WITH (NOLOCK)'
})

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末向楼,一起剝皮案震驚了整個(gè)濱河市查吊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜜自,老刑警劉巖菩貌,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異重荠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)虚茶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門戈鲁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嘹叫,你說我怎么就攤上這事婆殿。” “怎么了罩扇?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵婆芦,是天一觀的道長。 經(jīng)常有香客問我喂饥,道長消约,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任员帮,我火速辦了婚禮或粮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捞高。我一直安慰自己氯材,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布硝岗。 她就那樣靜靜地躺著氢哮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪型檀。 梳的紋絲不亂的頭發(fā)上冗尤,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼生闲。 笑死媳溺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碍讯。 我是一名探鬼主播悬蔽,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捉兴!你這毒婦竟也來了蝎困?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤倍啥,失蹤者是張志新(化名)和其女友劉穎禾乘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虽缕,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡始藕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了氮趋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伍派。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剩胁,靈堂內(nèi)的尸體忽然破棺而出诉植,到底是詐尸還是另有隱情,我是刑警寧澤昵观,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布晾腔,位于F島的核電站,受9級(jí)特大地震影響啊犬,放射性物質(zhì)發(fā)生泄漏灼擂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一椒惨、第九天 我趴在偏房一處隱蔽的房頂上張望缤至。 院中可真熱鬧,春花似錦康谆、人聲如沸领斥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽月洛。三九已至,卻和暖如春孽锥,著一層夾襖步出監(jiān)牢的瞬間嚼黔,已是汗流浹背细层。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留唬涧,地道東北人疫赎。 一個(gè)月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像碎节,于是被迫代替她去往敵國和親捧搞。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355