ThinkJS 中支持关联模型,让处理这类操作非常简单。

    关联模型中支持常见的 4 类关联关系。如:

    • think.model.HAS_ONE 一对一模型
    • think.model.BELONG_TO 一对一属于
    • think.model.HAS_MANY 一对多
    • think.model.MANY_TO_MANY 多对多

    可以通过命令 来创建关联模型。如:

    会创建模型文件 src/home/model/post.js

    可以通过 relation 属性来指定关联关系。如:

    1. export default class extends think.model.relation {
    2. init(...args){
    3. super.init(...args);
    4. //通过 relation 属性指定关联关系,可以指定多个关联关系
    5. this.relation = {
    6. cate: {},
    7. comment: {}
    8. };
    9. }
    10. }

    也可以直接使用 ES7 里的语法直接定义 relation 属性。如:

    1. export default class extends think.model.relation {
    2. //直接定义 relation 属性
    3. relation = {
    4. cate: {},
    5. comment: {}
    6. };
    7. init(...args){
    8. super.init(...args);
    9. }
    10. }

    单个关系模型的数据格式

    1. export default class extends think.model.relation {
    2. init(...args){
    3. super.init(...args);
    4. this.relation = {
    5. cate: {
    6. type: think.model.MANY_TO_MANY, //relation type
    7. model: '', //model name
    8. name: 'profile', //data name
    9. key: 'id',
    10. fKey: 'user_id', //forign key
    11. field: 'id,name',
    12. where: 'name=xx',
    13. order: '',
    14. limit: '',
    15. rModel: '',
    16. rfKey: ''
    17. },
    18. };
    19. }
    20. }

    各个字段含义如下:

    • type 关联关系类型
    • model 关联表的模型名,默认为配置的 key,这里为 cate
    • name 对应的数据字段名,默认为配置的 key,这里为 cate
    • key 当前模型的关联 key
    • fKey 关联表与只对应的 key
    • field 关联表查询时设置的 field,如果需要设置,必须包含 fKey 对应的值
    • where 关联表查询时设置的 where 条件
    • order 关联表查询时设置的 order
    • limit 关联表查询时设置的 limit
    • page 关联表查询时设置的 page
    • rModel 多对多下,对应的关联关系模型名
    1. export default class extends think.model.relation {
    2. init(...args){
    3. super.init(...args);
    4. this.relation = {
    5. cate: think.model.MANY_TO_MANY
    6. };
    7. }
    8. }

    HAS_ONE

    一对一关联,表示当前表含有一个附属表。

    假设当前表的模型名为 user,关联表的模型名为 info,那么配置中字段 key 的默认值为 id,字段 fKey 的默认值为 user_id

    1. export default class extends think.model.relation {
    2. init(..args){
    3. super.init(...args);
    4. this.relation = {
    5. info: think.model.HAS_ONE
    6. };
    7. }
    8. }

    BELONG_TO

    一对一关联,属于某个关联表,和 HAS_ONE 是相反的关系。

    假设当前模型名为 info,关联表的模型名为 user,那么配置字段 key 的默认值为 user_id,配置字段 fKey 的默认值为 id

    1. export default class extends think.model.relation {
    2. super.init(...args);
    3. this.relation = {
    4. user: think.model.BELONG_TO
    5. };
    6. }
    7. }

    执行查询操作时,可以得到类似下面的数据:

    1. [
    2. {
    3. id: 1,
    4. user_id: 1,
    5. desc: 'info',
    6. user: {
    7. name: 'thinkjs'
    8. }
    9. }, ...
    10. ]

    HAS_MANY

    一对多的关系。

    加入当前模型名为 post,关联表的模型名为 comment,那么配置字段 key 默认值为 id,配置字段 fKey 默认值为 post_id

    1. 'use strict';
    2. /**
    3. * relation model
    4. */
    5. export default class extends think.model.relation {
    6. init(...args){
    7. super.init(...args);
    8. this.relation = {
    9. comment: {
    10. type: think.model.HAS_MANY
    11. }
    12. };
    13. }
    14. }

    执行查询数据时,可以得到类似下面的数据:

    1. [{
    2. id: 1,
    3. title: 'first post',
    4. content: 'content',
    5. comment: [{
    6. id: 1,
    7. post_id: 1,
    8. name: 'welefen',
    9. content: 'first comment'
    10. }, ...]
    11. }, ...]

    如果关联表的数据需要分页查询,可以通过 page 参数进行,如:

    1. 'use strict';
    2. /**
    3. * relation model
    4. */
    5. export default class extends think.model.relation {
    6. init(...args){
    7. super.init(...args);
    8. this.relation = {
    9. comment: {
    10. type: think.model.HAS_MANY
    11. }
    12. }
    13. getList(page){
    14. return this.setRelation('comment', {page: page}).select();
    15. }
    16. }

    除了用 setRelation 来合并参数外,可以将参数设置为函数,合并参数时会自动执行该函数。

    MANY_TO_MANY

    多对多关系。

    查询出来的数据结构为:

    1. id: 1,
    2. title: 'first post',
    3. cate: [{
    4. id: 1,
    5. name: 'cate1',
    6. post_id: 1
    7. }, ...]
    8. }, ...]

    关联死循环

    如果 2 个关联表,一个设置对方为 HAS_ONE,另一个设置对方为 BELONG_TO,这样在查询关联表的数据时会将当前表又查询了一遍,并且会再次查询关联表,最终导致死循环。

    可以在配置里设置 relation 字段关闭关联表的关联查询功能,从而避免死循环。如:

    1. export default class extends think.model.relation {
    2. init(..args){
    3. super.init(...args);
    4. this.relation = {
    5. user: {
    6. type: think.model.BELONG_TO,
    7. relation: false //关联表 user 查询时关闭关联查询
    8. }
    9. };
    10. }
    11. }

    也可以设置只关闭当前模型的关联关系,如:

    1. export default class extends think.model.relation {
    2. init(..args){
    3. super.init(...args);
    4. this.relation = {
    5. user: {
    6. type: think.model.BELONG_TO,
    7. relation: 'info' //关联表 user 查询时关闭对 info 模型的关联关系
    8. }
    9. };
    10. }
    11. }

    设置关联关系后,查询等操作都会自动查询关联表的数据。如果某些情况下不需要查询关联表的数据,可以通过 setRelation 方法临时关闭关联关系查询。

    全部关闭

    通过 setRelation(false) 关闭所有的关联关系查询。

    1. export default class extends think.model.relation {
    2. init(...args){
    3. super.init(...args);
    4. this.relation = {
    5. comment: think.model.HAS_MANY,
    6. cate: think.model.MANY_TO_MANY
    7. };
    8. }
    9. getList(){
    10. return this.setRelation(false).select();
    11. }
    12. }

    部分启用

    通过 setRelation('comment') 只查询 comment 的关联数据,不查询其他的关联关系数据。

    1. export default class extends think.model.relation {
    2. init(...args){
    3. super.init(...args);
    4. this.relation = {
    5. comment: think.model.HAS_MANY,
    6. cate: think.model.MANY_TO_MANY
    7. };
    8. }
    9. getList2(){
    10. return this.setRelation('comment').select();
    11. }
    12. }

    部分关闭

    通过 setRelation('comment', false) 关闭 comment 的关联关系数据查询。

    重新全部启用

    通过 setRelation(true) 重新启用所有的关联关系数据查询。

    1. export default class extends think.model.relation {
    2. init(...args){
    3. super.init(...args);
    4. this.relation = {
    5. comment: think.model.HAS_MANY,
    6. cate: think.model.MANY_TO_MANY
    7. };
    8. }
    9. getList2(){
    10. return this.setRelation(true).select();
    11. }
    12. }