最近做了写公司中的基建工作,其中涉及到了 node 项目中使用 sequelize,同时有多对多的关系需要处理,便写了个关于 sequelize 处理多对多关系的练手示例,liuxy0551/sequelize-association,目前仅涉及查询,create
和update
暂未进行。
sql 语句 点此查看。
¶一、一对一
一对一的举例是:一个中国公民 (Chinese) 只有一个身份证号 (IDNumber) ,具体实现如下:
1 | const models = initModels(sequelize) |
1 | // service 层实现 |
接口返回的结果如下:
sequelize 自动生成的 sql 语句如下:
1 | SELECT |
¶二、一对多
一对多的举例是:一个省份 (Province) 有多个市 (City),具体实现如下:
1 | const models = initModels(sequelize) |
1 | // service 层实现 |
接口返回的结果如下:
sequelize 自动生成的 sql 语句如下:
1 | SELECT |
¶三、多对多
多对多的举例是:一部电影 (Movie) 有多个演员 (Actor), 一个演员 (Actor) 参演多部电影 (Movie),具体实现如下:
1 | const models = initModels(sequelize) |
1 | // service 层实现 |
接口返回的结果如下:
sequelize 自动生成的 sql 语句如下:
1 | -- 多对多 getActorListWithMovies |
1 | -- 多对多 getMovieListWithActors |
¶四、注意事项
1、在使用关联关系进行查询时,请求参数中不要使用raw: true
,raw
默认为 false,此时 sequelize 会自动拼接一些参数,设为 true 的话,会丢失参数导致数据结构错乱,如下图:
2、一对多时会出现返回的结果包含了大驼峰写法的关联 id 及值,可通过include attributes exclude
将该字段过滤;
3、多对多时,一般不需要展示关联表的字段,可通过include through attributes
将关联表字段过滤,如下:
1 | const { count, rows } = await DB.Actor.findAndCountAll({ |
4、建立关联关系时,可在app/utils/mysql/db.js
中进行,引入的 initModels 中导出了所有 model 层,可参考:app/utils/mysql/db.js。
5、多对多的关联查询可以分解为以下四条 sql 进行,在数据量大的时候能减少查询时间,也是简化 sql 语句的方法:
- 查询电影表的总数量 total
- 查询电影表前十条数据
- 拿着上述十条数据去关联表查询关联数据,对关联的演员信息进行去重
- 拿着上述去重后的演员信息在演员表中查询,由代码拼装数据再从接口返回
¶五、占坑文章
1、预先加载,参考 Sequelize 中文文档 - 预先加载
¶六、参考文章
练习过程中较多的参考了以下文章中提到的内容,在此感谢:
[1] Sequelize 中文文档 - 关联
[2] Sequelize 英文官网 Many-To-Many relationships