Sequelize 和 MySQL 对照
来源:SegmentFault
时间:2023-01-26 16:13:49 448浏览 收藏
有志者,事竟成!如果你在学习数据库,那么本文《Sequelize 和 MySQL 对照》,就很适合你!文章讲解的知识点主要包括MySQL、Node.js、javascript、sequelize,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~
如果你觉得Sequelize的文档有点多、杂,不方便看,可以看看这篇。
在使用
$ npm install --save co $ npm install --save sequelize $ npm install --save mysql
代码模板如下:
var Sequelize = require('sequelize'); var co = require('co'); co(function* () { // code here }).catch(function(e) { console.log(e); });
基本上,
var sequelize = new Sequelize( 'sample', // 数据库名 'root', // 用户名 'zuki', // 用户密码 { 'dialect': 'mysql', // 数据库使用mysql 'host': 'localhost', // 数据库服务器ip 'port': 3306, // 数据库服务器端口 'define': { // 字段以下划线(_)来分割(默认是驼峰命名风格) 'underscored': true } } );
定义单张表
var User = sequelize.define( // 默认表名(一般这里写单数),生成时会自动转换成复数形式 // 这个值还会作为访问模型相关的模型时的属性名,所以建议用小写形式 'user', // 字段定义(主键、created_at、updated_at默认包含,不用特殊定义) { 'emp_id': { 'type': Sequelize.CHAR(10), // 字段类型 'allowNull': false, // 是否允许为NULL 'unique': true // 字段是否UNIQUE }, 'nick': { 'type': Sequelize.CHAR(10), 'allowNull': false }, 'department': { 'type': Sequelize.STRING(64), 'allowNull': true } } );
CREATE TABLE IF NOT EXISTS `users` ( `id` INTEGER NOT NULL auto_increment , `emp_id` CHAR(10) NOT NULL UNIQUE, `nick` CHAR(10) NOT NULL, `department` VARCHAR(64), `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;
几点说明:
建表
var User = sequelize.define( 'user', { 'emp_id': { 'type': Sequelize.CHAR(10), // 字段类型 'allowNull': false, // 是否允许为NULL 'unique': true // 字段是否UNIQUE }, 'nick': { 'type': Sequelize.CHAR(10), 'allowNull': false }, 'department': { 'type': Sequelize.STRING(64), 'allowNull': true } }, { // 自定义表名 'freezeTableName': true, 'tableName': 'xyz_users', // 是否需要增加createdAt、updatedAt、deletedAt字段 'timestamps': true, // 不需要createdAt字段 'createdAt': false, // 将updatedAt字段改个名 'updatedAt': 'utime' // 将deletedAt字段改名 // 同时需要设置paranoid为true(此种模式下,删除数据时不会进行物理删除,而是设置deletedAt为当前时间 'deletedAt': 'dtime', 'paranoid': true } );
单表增删改查
通过
// 方法1:build后对象只存在于内存中,调用save后才操作db var user = User.build({ 'emp_id': '1', 'nick': '小红', 'department': '技术部' }); user = yield user.save(); console.log(user.get({'plain': true})); // 方法2:直接操作db var user = yield User.create({ 'emp_id': '2', 'nick': '小明', 'department': '技术部' }); console.log(user.get({'plain': true}));
INSERT INTO `users` (`id`, `emp_id`, `nick`, `department`, `updated_at`, `created_at`) VALUES (DEFAULT, '1', '小红', '技术部', '2015-11-02 14:49:54', '2015-11-02 14:49:54');
// 方法1:操作对象属性(不会操作db),调用save后操作db user.nick = '小白'; user = yield user.save(); console.log(user.get({'plain': true})); // 方法2:直接update操作db user = yield user.update({ 'nick': '小白白' }); console.log(user.get({'plain': true}));
UPDATE `users` SET `nick` = '小白白', `updated_at` = '2015-11-02 15:00:04' WHERE `id` = 1;
更新操作时,
// 方法1 user.emp_id = '33'; user.nick = '小白'; user = yield user.save({'fields': ['nick']}); // 方法2 user = yield user.update( {'emp_id': '33', 'nick': '小白'}, {'fields': ['nick']} });
这样就只会更新
yield user.destroy();
DELETE FROM `users` WHERE `id` = 1;
这里有个特殊的地方是,如果我们开启了
var users = yield User.findAll(); console.log(users);
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users`;
限制字段
var users = yield User.findAll({ 'attributes': ['emp_id', 'nick'] }); console.log(users);
SELECT `emp_id`, `nick` FROM `users`;
字段重命名
var users = yield User.findAll({ 'attributes': [ 'emp_id', ['nick', 'user_nick'] ] }); console.log(users);
SELECT `emp_id`, `nick` AS `user_nick` FROM `users`;
where子句
var users = yield User.findAll({ 'where': { 'id': [1, 2, 3], 'nick': 'a', 'department': null } }); console.log(users);
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE `user`.`id` IN (1, 2, 3) AND `user`.`nick`='a' AND `user`.`department` IS NULL;
可以看到,
var users = yield User.findAll({ 'where': { 'id': { '$eq': 1, // id = 1 '$ne': 2, // id != 2 '$gt': 6, // id > 6 '$gte': 6, // id >= 6 '$lt': 10, // id
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE ( `user`.`id` = 1 AND `user`.`id` != 2 AND `user`.`id` > 6 AND `user`.`id` >= 6 AND `user`.`id`
这里我们发现,其实相等条件
var users = yield User.findAll({ 'where': { '$and': [ {'id': [1, 2]}, {'nick': null} ] } });
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE ( `user`.`id` IN (1, 2) AND `user`.`nick` IS NULL );
OR条件
var users = yield User.findAll({ 'where': { '$or': [ {'id': [1, 2]}, {'nick': null} ] } });
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE ( `user`.`id` IN (1, 2) OR `user`.`nick` IS NULL );
NOT条件
var users = yield User.findAll({ 'where': { '$not': [ {'id': [1, 2]}, {'nick': null} ] } });
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE NOT ( `user`.`id` IN (1, 2) AND `user`.`nick` IS NULL );
转换规则
我们这里做个总结。
function translate(where) { for (k, v of where) { if (k == 表字段) { // 先统一转为操作符形式 if (v == 基本值) { // k: 'xxx' v = {'$eq': v}; } if (v == 数组) { // k: [1, 2, 3] v = {'$in': v}; } // 操作符转换 for (opk, opv of v) { // op将opk转换对应的SQL表示 => k + op(opk, opv) + AND; } } // 逻辑操作符处理 if (k == '$and') { for (item in v) { => translate(item) + AND; } } if (k == '$or') { for (item in v) { => translate(item) + OR; } } if (k == '$not') { NOT + for (item in v) { => translate(item) + AND; } } } function op(opk, opv) { switch (opk) { case $eq => ('=' + opv) || 'IS NULL'; case $ne => ('!=' + opv) || 'IS NOT NULL'; case $gt => '>' + opv; case $lt => ' '>=' + opv; case $lte => ' 'BETWEEN ' + opv[0] + ' AND ' + opv[1]; case $notBetween => 'NOT BETWEEN ' + opv[0] + ' AND ' + opv[1]; case $in => 'IN (' + opv.join(',') + ')'; case $notIn => 'NOT IN (' + opv.join(',') + ')'; case $like => 'LIKE ' + opv; case $notLike => 'NOT LIKE ' + opv; } } }
我们看一个复杂例子,基本上就是按上述流程来进行转换。
var users = yield User.findAll({ 'where': { 'id': [3, 4], '$not': [ { 'id': { '$in': [1, 2] } }, { '$or': [ {'id': [1, 2]}, {'nick': null} ] } ], '$and': [ {'id': [1, 2]}, {'nick': null} ], '$or': [ {'id': [1, 2]}, {'nick': null} ] } });
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE `user`.`id` IN (3, 4) AND NOT ( `user`.`id` IN (1, 2) AND (`user`.`id` IN (1, 2) OR `user`.`nick` IS NULL) ) AND ( `user`.`id` IN (1, 2) AND `user`.`nick` IS NULL ) AND ( `user`.`id` IN (1, 2) OR `user`.`nick` IS NULL );
排序
var users = yield User.findAll({ 'order': [ ['id', 'DESC'], ['nick'] ] });
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` ORDER BY `user`.`id` DESC, `user`.`nick`;
分页
var countPerPage = 20, currentPage = 5; var users = yield User.findAll({ 'limit': countPerPage, // 每页多少条 'offset': countPerPage * (currentPage - 1) // 跳过多少条 });
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` LIMIT 80, 20;
其他查询方法
查询一条数据
user = yield User.findById(1); user = yield User.findOne({ 'where': {'nick': 'a'} });
SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE `user`.`id` = 1 LIMIT 1; SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` WHERE `user`.`nick` = 'a' LIMIT 1;
查询并获取数量
var result = yield User.findAndCountAll({ 'limit': 20, 'offset': 0 }); console.log(result);
SELECT count(*) AS `count` FROM `users` AS `user`; SELECT `id`, `emp_id`, `nick`, `department`, `created_at`, `updated_at` FROM `users` AS `user` LIMIT 20;
这个方法会执行2个
var users = yield User.bulkCreate( [ {'emp_id': 'a', 'nick': 'a'}, {'emp_id': 'b', 'nick': 'b'}, {'emp_id': 'c', 'nick': 'c'} ] );
INSERT INTO `users` (`id`,`emp_id`,`nick`,`created_at`,`updated_at`) VALUES (NULL,'a','a','2015-11-03 02:43:30','2015-11-03 02:43:30'), (NULL,'b','b','2015-11-03 02:43:30','2015-11-03 02:43:30'), (NULL,'c','c','2015-11-03 02:43:30','2015-11-03 02:43:30');
这里需要注意,返回的
var affectedRows = yield User.update( {'nick': 'hhhh'}, { 'where': { 'id': [2, 3, 4] } } );
UPDATE `users` SET `nick`='hhhh',`updated_at`='2015-11-03 02:51:05' WHERE `id` IN (2, 3, 4);
这里返回的
var affectedRows = yield User.destroy({ 'where': {'id': [2, 3, 4]} });
DELETE FROM `users` WHERE `id` IN (2, 3, 4);
这里返回的
var User = sequelize.define('user', { 'emp_id': { 'type': Sequelize.CHAR(10), 'allowNull': false, 'unique': true } } ); var Account = sequelize.define('account', { 'email': { 'type': Sequelize.CHAR(20), 'allowNull': false } } ); /* * User的实例对象将拥有getAccount、setAccount、addAccount方法 */ User.hasOne(Account); /* * Account的实例对象将拥有getUser、setUser、addUser方法 */ Account.belongsTo(User);
CREATE TABLE IF NOT EXISTS `users` ( `id` INTEGER NOT NULL auto_increment , `emp_id` CHAR(10) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `accounts` ( `id` INTEGER NOT NULL auto_increment , `email` CHAR(20) NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `user_id` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE ) ENGINE=InnoDB;
可以看到,这种关系中外键
var user = yield User.create({'emp_id': '1'}); var account = user.createAccount({'email': 'a'}); console.log(account.get({'plain': true}));
INSERT INTO `users` (`id`,`emp_id`,`updated_at`,`created_at`) VALUES (DEFAULT,'1','2015-11-03 06:24:53','2015-11-03 06:24:53'); INSERT INTO `accounts` (`id`,`email`,`user_id`,`updated_at`,`created_at`) VALUES (DEFAULT,'a',1,'2015-11-03 06:24:53','2015-11-03 06:24:53');
var anotherAccount = yield Account.create({'email': 'b'}); console.log(anotherAccount); anotherAccount = yield user.setAccount(anotherAccount); console.log(anotherAccount);
INSERT INTO `accounts` (`id`,`email`,`updated_at`,`created_at`) VALUES (DEFAULT,'b','2015-11-03 06:37:14','2015-11-03 06:37:14'); SELECT `id`, `email`, `created_at`, `updated_at`, `user_id` FROM `accounts` AS `account` WHERE (`account`.`user_id` = 1); UPDATE `accounts` SET `user_id`=NULL,`updated_at`='2015-11-03 06:37:14' WHERE `id` = 1; UPDATE `accounts` SET `user_id`=1,`updated_at`='2015-11-03 06:37:14' WHERE `id` = 2;
yield user.setAccount(null);
SELECT `id`, `email`, `created_at`, `updated_at`, `user_id` FROM `accounts` AS `account` WHERE (`account`.`user_id` = 1); UPDATE `accounts` SET `user_id`=NULL,`updated_at`='2015-11-04 00:11:35' WHERE `id` = 1;
这里的删除实际上只是“切断”关系,并不会真正的物理删除记录。
var account = yield user.getAccount(); console.log(account);
SELECT `id`, `email`, `created_at`, `updated_at`, `user_id` FROM `accounts` AS `account` WHERE (`account`.`user_id` = 1);
这里就是调用
var user = yield User.findById(1, { 'include': [Account] }); console.log(user.get({'plain': true})); /* * 输出类似: { id: 1, emp_id: '1', created_at: Tue Nov 03 2015 15:25:27 GMT+0800 (CST), updated_at: Tue Nov 03 2015 15:25:27 GMT+0800 (CST), account: { id: 2, email: 'b', created_at: Tue Nov 03 2015 15:25:27 GMT+0800 (CST), updated_at: Tue Nov 03 2015 15:25:27 GMT+0800 (CST), user_id: 1 } } */
SELECT `user`.`id`, `user`.`emp_id`, `user`.`created_at`, `user`.`updated_at`, `account`.`id` AS `account.id`, `account`.`email` AS `account.email`, `account`.`created_at` AS `account.created_at`, `account`.`updated_at` AS `account.updated_at`, `account`.`user_id` AS `account.user_id` FROM `users` AS `user` LEFT OUTER JOIN `accounts` AS `account` ON `user`.`id` = `account`.`user_id` WHERE `user`.`id` = 1 LIMIT 1;
可以看到,我们对2个表进行了一个外联接,从而在取
var User = sequelize.define('user', { 'emp_id': { 'type': Sequelize.CHAR(10), 'allowNull': false, 'unique': true } } ); var Note = sequelize.define('note', { 'title': { 'type': Sequelize.CHAR(64), 'allowNull': false } } ); /* * User的实例对象将拥有getNotes、setNotes、addNote、createNote、removeNote、hasNote方法 */ User.hasMany(Note); /* * Note的实例对象将拥有getUser、setUser、createUser方法 */ Note.belongsTo(User);
CREATE TABLE IF NOT EXISTS `users` ( `id` INTEGER NOT NULL auto_increment , `emp_id` CHAR(10) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `notes` ( `id` INTEGER NOT NULL auto_increment , `title` CHAR(64) NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `user_id` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE ) ENGINE=InnoDB;
可以看到这种关系中,外键
var user = yield User.create({'emp_id': '1'}); var note = yield user.createNote({'title': 'a'}); console.log(note);
NSERT INTO `users` (`id`,`emp_id`,`updated_at`,`created_at`) VALUES (DEFAULT,'1','2015-11-03 23:52:05','2015-11-03 23:52:05'); INSERT INTO `notes` (`id`,`title`,`user_id`,`updated_at`,`created_at`) VALUES (DEFAULT,'a',1,'2015-11-03 23:52:05','2015-11-03 23:52:05');
var user = yield User.create({'emp_id': '1'}); var note = yield Note.create({'title': 'b'}); yield user.addNote(note);
INSERT INTO `users` (`id`,`emp_id`,`updated_at`,`created_at`) VALUES (DEFAULT,'1','2015-11-04 00:02:56','2015-11-04 00:02:56'); INSERT INTO `notes` (`id`,`title`,`updated_at`,`created_at`) VALUES (DEFAULT,'b','2015-11-04 00:02:56','2015-11-04 00:02:56'); UPDATE `notes` SET `user_id`=1,`updated_at`='2015-11-04 00:02:56' WHERE `id` IN (1);
// 为user增加note1、note2 var user = yield User.create({'emp_id': '1'}); var note1 = yield user.createNote({'title': 'a'}); var note2 = yield user.createNote({'title': 'b'}); // 先创建note3、note4 var note3 = yield Note.create({'title': 'c'}); var note4 = yield Note.create({'title': 'd'}); // user拥有的note更改为note3、note4 yield user.setNotes([note3, note4]);
/* 省去了创建语句 */ SELECT `id`, `title`, `created_at`, `updated_at`, `user_id` FROM `notes` AS `note` WHERE `note`.`user_id` = 1; UPDATE `notes` SET `user_id`=NULL,`updated_at`='2015-11-04 12:45:12' WHERE `id` IN (1, 2); UPDATE `notes` SET `user_id`=1,`updated_at`='2015-11-04 12:45:12' WHERE `id` IN (3, 4);
var user = yield User.create({'emp_id': '1'}); var note1 = yield user.createNote({'title': 'a'}); var note2 = yield user.createNote({'title': 'b'}); yield user.setNotes([]);
SELECT `id`, `title`, `created_at`, `updated_at`, `user_id` FROM `notes` AS `note` WHERE `note`.`user_id` = 1; UPDATE `notes` SET `user_id`=NULL,`updated_at`='2015-11-04 12:50:08' WHERE `id` IN (1, 2);
实际上,上面说到的“改”已经有“删”的操作了(去掉
yield user.removeNote(note);
UPDATE `notes` SET `user_id`=NULL,`updated_at`='2015-11-06 01:40:12' WHERE `user_id` = 1 AND `id` IN (1);
查
情况1
查询
var notes = yield user.getNotes({ 'where': { 'title': { '$like': '%css%' } } }); notes.forEach(function(note) { console.log(note); });
SELECT `id`, `title`, `created_at`, `updated_at`, `user_id` FROM `notes` AS `note` WHERE (`note`.`user_id` = 1 AND `note`.`title` LIKE '%a%');
这种方法的
var notes = yield Note.findAll({ 'include': [User], 'where': { 'title': { '$like': '%css%' } } }); notes.forEach(function(note) { // note属于哪个user可以通过note.user访问 console.log(note); });
SELECT `note`.`id`, `note`.`title`, `note`.`created_at`, `note`.`updated_at`, `note`.`user_id`, `user`.`id` AS `user.id`, `user`.`emp_id` AS `user.emp_id`, `user`.`created_at` AS `user.created_at`, `user`.`updated_at` AS `user.updated_at` FROM `notes` AS `note` LEFT OUTER JOIN `users` AS `user` ON `note`.`user_id` = `user`.`id` WHERE `note`.`title` LIKE '%css%';
这种方法,因为获取的主体是
var users = yield User.findAll({ 'include': [Note], 'where': { 'created_at': { '$lt': new Date() } } }); users.forEach(function(user) { // user的notes可以通过user.notes访问 console.log(user); });
SELECT `user`.`id`, `user`.`emp_id`, `user`.`created_at`, `user`.`updated_at`, `notes`.`id` AS `notes.id`, `notes`.`title` AS `notes.title`, `notes`.`created_at` AS `notes.created_at`, `notes`.`updated_at` AS `notes.updated_at`, `notes`.`user_id` AS `notes.user_id` FROM `users` AS `user` LEFT OUTER JOIN `notes` AS `notes` ON `user`.`id` = `notes`.`user_id` WHERE `user`.`created_at`
这种方法获取的主体是
// 查询创建时间在今天之前的所有user,同时获取他们note的标题中含有关键字css的所有note var users = yield User.findAll({ 'include': [ { 'model': Note, 'where': { 'title': { '$like': '%css%' } } } ], 'where': { 'created_at': { '$lt': new Date() } } });
SELECT `user`.`id`, `user`.`emp_id`, `user`.`created_at`, `user`.`updated_at`, `notes`.`id` AS `notes.id`, `notes`.`title` AS `notes.title`, `notes`.`created_at` AS `notes.created_at`, `notes`.`updated_at` AS `notes.updated_at`, `notes`.`user_id` AS `notes.user_id` FROM `users` AS `user` INNER JOIN `notes` AS `notes` ON `user`.`id` = `notes`.`user_id` AND `notes`.`title` LIKE '%css%' WHERE `user`.`created_at`
注意:当我们对
var Note = sequelize.define('note', { 'title': { 'type': Sequelize.CHAR(64), 'allowNull': false } } ); var Tag = sequelize.define('tag', { 'name': { 'type': Sequelize.CHAR(64), 'allowNull': false, 'unique': true } } ); var Tagging = sequelize.define('tagging', { 'type': { 'type': Sequelize.INTEGER(), 'allowNull': false } } ); // Note的实例拥有getTags、setTags、addTag、addTags、createTag、removeTag、hasTag方法 Note.belongsToMany(Tag, {'through': Tagging}); // Tag的实例拥有getNotes、setNotes、addNote、addNotes、createNote、removeNote、hasNote方法 Tag.belongsToMany(Note, {'through': Tagging});
CREATE TABLE IF NOT EXISTS `notes` ( `id` INTEGER NOT NULL auto_increment , `title` CHAR(64) NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `tags` ( `id` INTEGER NOT NULL auto_increment , `name` CHAR(64) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `taggings` ( `type` INTEGER NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `tag_id` INTEGER , `note_id` INTEGER , PRIMARY KEY (`tag_id`, `note_id`), FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`note_id`) REFERENCES `notes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB;
可以看到,多对多关系中单独生成了一张关系表,并设置了2个外键
var note = yield Note.create({'title': 'note'}); yield note.createTag({'name': 'tag'}, {'type': 0});
INSERT INTO `notes` (`id`,`title`,`updated_at`,`created_at`) VALUES (DEFAULT,'note','2015-11-06 02:14:38','2015-11-06 02:14:38'); INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag','2015-11-06 02:14:38','2015-11-06 02:14:38'); INSERT INTO `taggings` (`tag_id`,`note_id`,`type`,`created_at`,`updated_at`) VALUES (1,1,0,'2015-11-06 02:14:38','2015-11-06 02:14:38');
var note = yield Note.create({'title': 'note'}); var tag = yield Tag.create({'name': 'tag'}); yield note.addTag(tag, {'type': 1});
INSERT INTO `notes` (`id`,`title`,`updated_at`,`created_at`) VALUES (DEFAULT,'note','2015-11-06 02:20:52','2015-11-06 02:20:52'); INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag','2015-11-06 02:20:52','2015-11-06 02:20:52'); INSERT INTO `taggings` (`tag_id`,`note_id`,`type`,`created_at`,`updated_at`) VALUES (1,1,1,'2015-11-06 02:20:52','2015-11-06 02:20:52');
这种方法和上面的方法实际上是一样的。只是我们先手动
var note = yield Note.create({'title': 'note'}); var tag1 = yield Tag.create({'name': 'tag1'}); var tag2 = yield Tag.create({'name': 'tag2'}); yield note.addTags([tag1, tag2], {'type': 2});
INSERT INTO `notes` (`id`,`title`,`updated_at`,`created_at`) VALUES (DEFAULT,'note','2015-11-06 02:25:18','2015-11-06 02:25:18'); INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag1','2015-11-06 02:25:18','2015-11-06 02:25:18'); INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag2','2015-11-06 02:25:18','2015-11-06 02:25:18'); INSERT INTO `taggings` (`tag_id`,`note_id`,`type`,`created_at`,`updated_at`) VALUES (1,1,2,'2015-11-06 02:25:18','2015-11-06 02:25:18'), (2,1,2,'2015-11-06 02:25:18','2015-11-06 02:25:18');
这种方法可以进行批量添加。当执行
// 先添加几个tag var note = yield Note.create({'title': 'note'}); var tag1 = yield Tag.create({'name': 'tag1'}); var tag2 = yield Tag.create({'name': 'tag2'}); yield note.addTags([tag1, tag2], {'type': 2}); // 将tag改掉 var tag3 = yield Tag.create({'name': 'tag3'}); var tag4 = yield Tag.create({'name': 'tag4'}); yield note.setTags([tag3, tag4], {'type': 3});
/* 前面添加部分的sql,和上面一样*/ INSERT INTO `notes` (`id`,`title`,`updated_at`,`created_at`) VALUES (DEFAULT,'note','2015-11-06 02:25:18','2015-11-06 02:25:18'); INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag1','2015-11-06 02:25:18','2015-11-06 02:25:18'); INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag2','2015-11-06 02:25:18','2015-11-06 02:25:18'); INSERT INTO `taggings` (`tag_id`,`note_id`,`type`,`created_at`,`updated_at`) VALUES (1,1,2,'2015-11-06 02:25:18','2015-11-06 02:25:18'), (2,1,2,'2015-11-06 02:25:18','2015-11-06 02:25:18'); /* 更改部分的sql */ INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag3','2015-11-06 02:29:55','2015-11-06 02:29:55'); INSERT INTO `tags` (`id`,`name`,`updated_at`,`created_at`) VALUES (DEFAULT,'tag4','2015-11-06 02:29:55','2015-11-06 02:29:55'); /* 先删除关系 */ DELETE FROM `taggings` WHERE `note_id` = 1 AND `tag_id` IN (1, 2); /* 插入新关系 */ INSERT INTO `taggings` (`tag_id`,`note_id`,`type`,`created_at`,`updated_at`) VALUES (3,1,3,'2015-11-06 02:29:55','2015-11-06 02:29:55'), (4,1,3,'2015-11-06 02:29:55','2015-11-06 02:29:55');
执行逻辑是,先将
// 先添加几个tag var note = yield Note.create({'title': 'note'}); var tag1 = yield Tag.create({'name': 'tag1'}); var tag2 = yield Tag.create({'name': 'tag2'}); var tag3 = yield Tag.create({'name': 'tag2'}); yield note.addTags([tag1, tag2, tag3], {'type': 2}); // 删除一个 yield note.removeTag(tag1); // 全部删除 yield note.setTags([]);
/* 删除一个 */ DELETE FROM `taggings` WHERE `note_id` = 1 AND `tag_id` IN (1); /* 删除全部 */ SELECT `type`, `created_at`, `updated_at`, `tag_id`, `note_id` FROM `taggings` AS `tagging` WHERE `tagging`.`note_id` = 1; DELETE FROM `taggings` WHERE `note_id` = 1 AND `tag_id` IN (2, 3);
删除一个很简单,直接将关系表中的数据删除。
全部删除时,首先需要查出关系表中
var tags = yield note.getTags({ //这里可以对tags进行where }); tags.forEach(function(tag) { // 关系模型可以通过tag.tagging来访问 console.log(tag); });
SELECT `tag`.`id`, `tag`.`name`, `tag`.`created_at`, `tag`.`updated_at`, `tagging`.`type` AS `tagging.type`, `tagging`.`created_at` AS `tagging.created_at`, `tagging`.`updated_at` AS `tagging.updated_at`, `tagging`.`tag_id` AS `tagging.tag_id`, `tagging`.`note_id` AS `tagging.note_id` FROM `tags` AS `tag` INNER JOIN `taggings` AS `tagging` ON `tag`.`id` = `tagging`.`tag_id` AND `tagging`.`note_id` = 1;
可以看到这种查询,就是执行一个
var tags = yield Tag.findAll({ 'include': [ { 'model': Note // 这里可以对notes进行where } ] // 这里可以对tags进行where }); tags.forEach(function(tag) { // tag的notes可以通过tag.notes访问,关系模型可以通过tag.notes[0].tagging访问 console.log(tag); });
SELECT `tag`.`id`, `tag`.`name`, `tag`.`created_at`, `tag`.`updated_at`, `notes`.`id` AS `notes.id`, `notes`.`title` AS `notes.title`, `notes`.`created_at` AS `notes.created_at`, `notes`.`updated_at` AS `notes.updated_at`, `notes.tagging`.`type` AS `notes.tagging.type`, `notes.tagging`.`created_at` AS `notes.tagging.created_at`, `notes.tagging`.`updated_at` AS `notes.tagging.updated_at`, `notes.tagging`.`tag_id` AS `notes.tagging.tag_id`, `notes.tagging`.`note_id` AS `notes.tagging.note_id` FROM `tags` AS `tag` LEFT OUTER JOIN ( `taggings` AS `notes.tagging` INNER JOIN `notes` AS `notes` ON `notes`.`id` = `notes.tagging`.`note_id` ) ON `tag`.`id` = `notes.tagging`.`tag_id`;
这个查询就稍微有点复杂。首先是
var notes = yield Note.findAll({ 'include': [ { 'model': Tag // 这里可以对tags进行where } ] // 这里可以对notes进行where }); notes.forEach(function(note) { // note的tags可以通过note.tags访问,关系模型通过note.tags[0].tagging访问 console.log(note); });
SELECT `note`.`id`, `note`.`title`, `note`.`created_at`, `note`.`updated_at`, `tags`.`id` AS `tags.id`, `tags`.`name` AS `tags.name`, `tags`.`created_at` AS `tags.created_at`, `tags`.`updated_at` AS `tags.updated_at`, `tags.tagging`.`type` AS `tags.tagging.type`, `tags.tagging`.`created_at` AS `tags.tagging.created_at`, `tags.tagging`.`updated_at` AS `tags.tagging.updated_at`, `tags.tagging`.`tag_id` AS `tags.tagging.tag_id`, `tags.tagging`.`note_id` AS `tags.tagging.note_id` FROM `notes` AS `note` LEFT OUTER JOIN ( `taggings` AS `tags.tagging` INNER JOIN `tags` AS `tags` ON `tags`.`id` = `tags.tagging`.`tag_id` ) ON `note`.`id` = `tags.tagging`.`note_id`;
这个查询和上面的查询类似。首先是
tags
和taggins
进行了一个inner join
,选出tags
;然后notes
和刚join
出的集合再做一次left join
,得到结果。其他没有涉及东西
这篇文章已经够长了,但是其实我们还有很多没有涉及的东西,比如:聚合函数及查询(
having
、group by
)、模型的验证(validate
)、定义钩子(hooks
)、索引等等。这些主题下次再来写写。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于数据库的相关知识,也可关注golang学习网公众号。
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
-
467 收藏
-
303 收藏
-
176 收藏
-
368 收藏
-
475 收藏
-
266 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习