簡單的講就是對SQL查詢語句的封裝,讓咱們能夠用OOP的方式操做數據庫,優雅的生成安全、可維護的SQL代碼。直觀上,是一種Model和SQL的映射關係。javascript
BOOLEAN 布爾類型 STRING 字符串類型,相似varchar CHAR 定長字符串 TEXT 文本類型 INTEGER 整數類型 FLOAT DOUBLE DECIMAL DATE ENUM 枚舉類型 NOW 當前時間戳 UUID UUID類型列,其默認值能夠爲UUIDV1或UUIDV4 UUIDV1 v1:是基於時間的uuid,經過計算當前時間戳、隨機數和機器MAC地址獲得。 UUIDV2 v4:根據隨機數,或者僞隨機數生成UUID uuid.v4().replace(/\-/g, '') //去除‘-’
id: { type: Sequelize.UUIDV4, primaryKey: true, // 主鍵 allowNull: false, //不爲空 // autoIncrement: true, //自增 unique: true, defaultValue: NOW, //默認值的設置 comment:'', // 說明 validate: { is: ["^[a-z]+$",'i'], // 只容許字母 is: /^[a-z]+$/i, // 只容許字母 not: ["[a-z]",'i'], // 不能使用字母 isEmail: true, // 檢測郵箱格式 (foo@bar.com) isUrl: true, // 檢查Url格式 (http://foo.com) isIP: true, // 檢查 IPv4 或 IPv6 格式 isIPv4: true, // 檢查 IPv4 isIPv6: true, // 檢查 IPv6 isAlpha: true, // 不能使用字母 isAlphanumeric: true, // 只容許字母數字字符 isNumeric: true, // 只能使用數字 isInt: true, // 只能是整數 isFloat: true, // 只能是浮點數 isDecimal: true, // 檢查數字 isLowercase: true, // 檢查小寫字母 isUppercase: true, // 檢查大寫字母 notNull: true, // 不容許null isNull: true, // 只能爲null notEmpty: true, // 不能空字符串 equals: 'specific value', // 只能使用指定值 contains: 'foo', // 必須包含子字符串 notIn: [['foo', 'bar']], // 不能是數組中的任意一個值 isIn: [['foo', 'bar']], // 只能是數組中的任意一個值 notContains: 'bar', // 不能包含子字符串 len: [2, 10], // 值的長度必在 2 和 10 之間 isUUID: 4, // 只能是UUID isDate: true, // 只能是日期字符串 isAfter: "2011-11-05", // 只能使用指定日期以後的時間 isBefore: "2011-11-05", // 只能使用指定日期以前的時間 max: 23, // 容許的最大值 min: 23, // 容許的最小值 isArray: true, // 不能使用數組 isCreditCard: true, // 檢查是有效的信用卡 // 也能夠自定義驗證: isEven: function(value) { if(parseInt(value) % 2 != 0) { throw new Error('Only even values are allowed!') // we also are in the model's context here, so this.otherField // would get the value of otherField if it existed } } }, // 假設暱稱後要加上 id 值 get() { const id = this.getDataValue('id'); return this.getDataValue('nickName') + '-' + id; }, // set 假設數據庫中存儲的郵箱都要是大寫的,能夠在此處改寫 set(val) { this.setDataValue('email', val.toUpperCase()); }, },
詳情看官方文檔java
await Role.findById(1);
node
await Role.findByPk(123)
await Role.findOne({ where: { level: 1, }, attributes: ['id', 'role_id'] });
await Role.findAndCountAll({ where: { level: 1, } });
await Role.all({ where: { level: { [Op.gt]: 1, // [Op.and]: {a: 5}, // AND (a = 5) // [Op.or]: [{a: 5}, {a: 6}], // (a = 5 OR 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.between]: [6, 10], // BETWEEN 6 AND 10 // [Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15 // [Op.in]: [1, 2], // IN [1, 2] // [Op.notIn]: [1, 2], // NOT IN [1, 2] // [Op.like]: '%hat', // LIKE '%hat' // [Op.notLike]: '%hat', // NOT LIKE '%hat' $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 } }, limit: 3, // 注意 raw, 默認爲 false, 這時候 Sequelize 會爲搜索出的每一條數據生成一個 Role 實例,用於更新,刪除等操做 // 但當咱們只想搜索出數據用於顯示,並不想操做它,這個時候設置 raw: true 就會直接返回數據,而不會生成實例 raw: true, });
await Role.count();
mysql
await Role.findAndCountAll({ where: { title: { [Op.like]: 'foo%' } }, offset: 10, limit: 2 })
await Role.findAndCountAll({ where: { title: { [Op.like]: 'foo%' } }, offset: 10, limit: 2 })
const user = await User.findOne({ where:{ id:userId }, attributes:[['id','user_id'],['username','user_name']] })
await Role.findAll({ 'order': "id DESC" }); Role.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') })
// 獲取10個實例/行 Project.findAll({ limit: 10 })
// 跳過8個實例/行 Project.findAll({ offset: 8 })
await Role.max('level', { where: { id: { [Op.gt]: 5, } } });
await Role.sum('level');
// 可使用sequelize.fn來執行這些函數 Role.findAll({ attributes: [[sequelize.fn('COUNT', sequelize.col('*')), 'total_count']], }); // SELECT COUNT(*) AS `total_count` ... Role.findAll({ attributes: [[sequelize.fn('COUNT', 1), 'total_count']], }); // SELECT COUNT(1) AS `total_count` ...
Role.findAll({ where: { [Op.or]: [{ id: 2 }, { id: 3 }], }, }); // ... where `role`.`id` = 2 OR `role`.`id` = 3 // 另外一種寫法 Role.findAll({ where: { id: { [Op.or]: [2, 3], }, }, }); // ... where `role`.`id` = 2 OR `role`.`id` = 3 // 不一樣字段的寫法 Role.findAll({ where: { [Op.or]: [{ id: 2 }, { level: 3 }], }, }); // ... where `role`.`id` = 2 OR `role`.`level` = 3 Role.findAll({ where: { [Op.or]: [{ id: 2 }, { level: 3 }], [Op.and]: [{ role_id: { [Op.ne]: 10001 } }], }, }); // ... where (`role`.`id` = 2 OR `role`.`level` = 3) AND (`role`.`role_id` != 10001)
await Role.findOrCreate({ where: { role_name: 'alex' }, defaults: { role_id: 5, role_name: 'alex', level: 15, }, });
const role = Role.build({ role_id: 1, role_name: 'name-1' }); await role.save(); // 在須要的時候調用 save 命令,能夠將數據存入數據庫中
await Role.create({ role_id: 2, role_name: 'name-2', });
const l = []; for (let i = 0; i < 5; i++) { l.push({ role_id: 1000 + i, role_name: `bulkname-${i}`, level: i + 5, }); } const result = await Role.bulkCreate(l, { // 這樣建立語句中只有 role_id 和 role_name,會忽略 level fields: ['role_id', 'role_name'] });
await Role.update({ level: 4 }, { where: {} });
const role = await Role.findOne({ where: {} }); await role.update({ // 注意這個role不是原型Role level: 5 });
// level加5 const role = await Role.findById(1); await role.increment('level', { by: 5 });
await Role.destroy({ where: { id: 1 } });
默認狀況下,函數將返回兩個參數 - 一個結果數組,以及一個包含元數據(受影響的行等)的對象。 請注意,因爲這是一個原始查詢,因此元數據(屬性名稱等)是具體的方言。 某些方言返回元數據 "within" 結果對象(做爲數組上的屬性)。 可是,將永遠返回兩個參數,但對於MSSQL和MySQL,它將是對同一對象的兩個引用。sql
const result1 = await mysql.query('SELECT id, img_url, url from carousel where status = 1'); //返回值是兩個相同元素組成的數組 "result1": [ [ { "id": 1, "url": "/ClassDetail?id=4" }, { "id": 4, "url": "/ClassDetail?id=2" } ], [ { "id": 1, "url": "/ClassDetail?id=4" }, { "id": 4, "url": "/ClassDetail?id=2" } ] ]
解決辦法有兩種數據庫
const result= await mysql.query('SELECT id, img_url, url from carousel where status = 1', { replacements: {}, type: mysql.QueryTypes.SELECT });
const Carousel = require('../../models/Carousel'); const result2 = await mysql.query('SELECT id, img_url, url from carousel where status = 1',{ model: Carousel });
查詢中的替換能夠經過兩種不一樣的方式完成:使用命名參數(以:開頭),或者由?表示的未命名參數。 替換在options對象中傳遞。npm
若是傳遞一個數組, ? 將按照它們在數組中出現的順序被替換segmentfault
const banner2 = await mysql.query('SELECT id, img_url, url from carousel where id = ?', { replacements: [1,4,5,6], type: mysql.QueryTypes.SELECT, }); // 返回的結果只有數組第一個元素下標對應的數據
const banner3 = await mysql.query('SELECT id, img_url, url from carousel where id in (:[1,4,5,6])', { replacements: {[1,4,5,6]}, type: mysql.QueryTypes.SELECT, }); // 返回結果爲符合數組的數據 // 拓展:模糊查詢 sequelize.query('SELECT * FROM users WHERE name LIKE :search_name ', { replacements: { search_name: 'ben%' }, type: sequelize.QueryTypes.SELECT } ).then(projects => { console.log(projects) }) 注意: type: mysql.QueryTypes.SELECT 進行不一樣的原生操做是, QueryTypes的取值也不相同,這裏誤覺得都是select坑死
參考文檔:
官方文檔
Sequelize 中文文檔 v4 - Raw queries - 原始查詢
alex_my https://blog.csdn.net/alex_my...api
若是不想讓它自動包裝,能夠在查詢的時候,設置一個參數就會返回查詢的源數據
Model.findAll({ raw: true, // 設置爲 true,便可返回源數據 //Other parameters });
也能夠在初始化 Sequelize 的時候直接全局設置:
const sequelize = new Sequelize('connectionUri', { define: { raw: true // 設置爲 true,便可返回源數據 } });