ThinkJS 關(guān)聯(lián)模型

2021-09-17 14:34 更新

關(guān)聯(lián)模型

數(shù)據(jù)庫中表經(jīng)常會(huì)跟其他數(shù)據(jù)表有關(guān)聯(lián),數(shù)據(jù)操作時(shí)需要連同關(guān)聯(lián)的表一起操作。如:一個(gè)博客文章會(huì)有分類、標(biāo)簽、評(píng)論,以及屬于哪個(gè)用戶。

ThinkJS 中支持關(guān)聯(lián)模型,讓處理這類操作非常簡(jiǎn)單。

支持的類型

關(guān)聯(lián)模型中支持常見的 4 類關(guān)聯(lián)關(guān)系。如:

  • think.model.HAS_ONE 一對(duì)一模型
  • think.model.BELONG_TO 一對(duì)一屬于
  • think.model.HAS_MANY 一對(duì)多
  • think.model.MANY_TO_MANY 多對(duì)多

創(chuàng)建關(guān)聯(lián)模型

可以通過命令 thinkjs model [name] --relation 來創(chuàng)建關(guān)聯(lián)模型。如:

thinkjs model home/post --relation

會(huì)創(chuàng)建模型文件 src/home/model/post.js。

指定關(guān)聯(lián)關(guān)系

可以通過 relation 屬性來指定關(guān)聯(lián)關(guān)系。如:

export default class extends think.model.relation {
  init(...args){
    super.init(...args);
    //通過 relation 屬性指定關(guān)聯(lián)關(guān)系,可以指定多個(gè)關(guān)聯(lián)關(guān)系
    this.relation = {
      cate: {},
      comment: {} 
    }
  }
}

也可以直接使用 ES7 里的語法直接定義 relation 屬性。如:

export default class extends think.model.relation {

  //直接定義 relation 屬性
  relation = {
    cate: {},
    comment: {} 
  }

  init(...args){
    super.init(...args);
  }
}

單個(gè)關(guān)系模型的數(shù)據(jù)格式

export default class extends think.model.relation {
  init(...args){
    super.init(...args);
    this.relation = {
      cate: {
        type: think.model.MANY_TO_MANY, //relation type
        model: "", //model name
        name: "profile", //data name
        key: "id", 
        fKey: "user_id", //forign key
        field: "id,name",
        where: "name=xx",
        order: "",
        limit: "",
        rModel: "",
        rfKey: ""
      },
    }
  }
}

各個(gè)字段含義如下:

  • type 關(guān)聯(lián)關(guān)系類型
  • model 關(guān)聯(lián)表的模型名,默認(rèn)為配置的 key,這里為 cate
  • name 對(duì)應(yīng)的數(shù)據(jù)字段名,默認(rèn)為配置的 key,這里為 cate
  • key 當(dāng)前模型的關(guān)聯(lián) key
  • fKey 關(guān)聯(lián)表與只對(duì)應(yīng)的 key
  • field 關(guān)聯(lián)表查詢時(shí)設(shè)置的 field,如果需要設(shè)置,必須包含 fKey 對(duì)應(yīng)的值
  • where 關(guān)聯(lián)表查詢時(shí)設(shè)置的 where 條件
  • order 關(guān)聯(lián)表查詢時(shí)設(shè)置的 order
  • limit 關(guān)聯(lián)表查詢時(shí)設(shè)置的 limit
  • page 關(guān)聯(lián)表查詢時(shí)設(shè)置的 page
  • rModel 多對(duì)多下,對(duì)應(yīng)的關(guān)聯(lián)關(guān)系模型名
  • rfKey 多對(duì)多下,對(duì)應(yīng)里的關(guān)系關(guān)系表對(duì)應(yīng)的 key

如果只用設(shè)置關(guān)聯(lián)類型,不用設(shè)置其他字段信息,可以通過下面簡(jiǎn)單的方式:

export default class extends think.model.relation {
  init(...args){
    super.init(...args);
    this.relation = {
      cate: think.model.MANY_TO_MANY
    }
  }
}

HAS_ONE

一對(duì)一關(guān)聯(lián),表示當(dāng)前表含有一個(gè)附屬表。

假設(shè)當(dāng)前表的模型名為 user,關(guān)聯(lián)表的模型名為 info,那么配置中字段 key 的默認(rèn)值為 id,字段 fKey的默認(rèn)值為 user_id

export default class extends think.model.relation {
  init(..args){
    super.init(...args);
    this.relation = {
      info: think.model.HAS_ONE
    }
  }
}

執(zhí)行查詢操作時(shí),可以得到類似如下的數(shù)據(jù):

[
  {
    id: 1,
    name: "111",
    info: { //關(guān)聯(lián)表里的數(shù)據(jù)信息
      user_id: 1,
      desc: "info"
    }
  }, ...]

BELONG_TO

一對(duì)一關(guān)聯(lián),屬于某個(gè)關(guān)聯(lián)表,和 HAS_ONE 是相反的關(guān)系。

假設(shè)當(dāng)前模型名為 info,關(guān)聯(lián)表的模型名為 user,那么配置字段 key 的默認(rèn)值為 user_id,配置字段fKey 的默認(rèn)值為 id。

export default class extends think.model.relation {
  init(..args){
    super.init(...args);
    this.relation = {
      user: think.model.BELONG_TO
    }
  }
}

執(zhí)行查詢操作時(shí),可以得到類似下面的數(shù)據(jù):

[
  {
    id: 1,
    user_id: 1,
    desc: "info",
    user: {
      name: "thinkjs"
    }
  }, ...
]

HAS_MANY

一對(duì)多的關(guān)系。

加入當(dāng)前模型名為 post,關(guān)聯(lián)表的模型名為 comment,那么配置字段 key 默認(rèn)值為 id,配置字段 fKey 默認(rèn)值為 post_id。

"use strict";
/**
 * relation model
 */
export default class extends think.model.relation {
  init(...args){
    super.init(...args);

    this.relation = {
      comment: {
        type: think.model.HAS_MANY
      }
    }
  }
}

執(zhí)行查詢數(shù)據(jù)時(shí),可以得到類似下面的數(shù)據(jù):

[{
  id: 1,
  title: "first post",
  content: "content",
  comment: [{
    id: 1,
    post_id: 1,
    name: "welefen",
    content: "first comment"
  }, ...]
}, ...]

如果關(guān)聯(lián)表的數(shù)據(jù)需要分頁查詢,可以通過 page 參數(shù)進(jìn)行,如:

"use strict";
/**
 * relation model
 */
export default class extends think.model.relation {
  init(...args){
    super.init(...args);

    this.relation = {
      comment: {
        type: think.model.HAS_MANY
      }
    }
  }
  getList(page){
    return this.setRelation("comment", {page: page}).select();
  }
}

除了用 setRelation 來合并參數(shù)外,可以將參數(shù)設(shè)置為函數(shù),合并參數(shù)時(shí)會(huì)自動(dòng)執(zhí)行該函數(shù)。

MANY_TO_MANY

多對(duì)多關(guān)系。

假設(shè)當(dāng)前模型名為 post,關(guān)聯(lián)模型名為 cate,那么需要一個(gè)對(duì)應(yīng)的關(guān)聯(lián)關(guān)系表。配置字段 rModel 默認(rèn)值為post_cate,配置字段 rfKey 默認(rèn)值為 cate_id

"use strict";
/**
 * relation model
 */
export default class extends think.model.relation {
  init(...args){
    super.init(...args);

    this.relation = {
      cate: {
        type: think.model.MANY_TO_MANY,
        rModel: "post_cate",
        rfKey: "cate_id"
      }
    }
  }
}

查詢出來的數(shù)據(jù)結(jié)構(gòu)為:

[{
  id: 1,
  title: "first post",
  cate: [{
    id: 1,
    name: "cate1",
    post_id: 1
  }, ...]
}, ...]

關(guān)聯(lián)死循環(huán)

如果 2 個(gè)關(guān)聯(lián)表,一個(gè)設(shè)置對(duì)方為 HAS_ONE,另一個(gè)設(shè)置對(duì)方為 BELONG_TO,這樣在查詢關(guān)聯(lián)表的數(shù)據(jù)時(shí)會(huì)將當(dāng)前表又查詢了一遍,并且會(huì)再次查詢關(guān)聯(lián)表,最終導(dǎo)致死循環(huán)。

可以在配置里設(shè)置 relation 字段關(guān)閉關(guān)聯(lián)表的關(guān)聯(lián)查詢功能,從而避免死循環(huán)。如:

export default class extends think.model.relation {
  init(..args){
    super.init(...args);
    this.relation = {
      user: {
        type: think.model.BELONG_TO,
        relation: false //關(guān)聯(lián)表 user 查詢時(shí)關(guān)閉關(guān)聯(lián)查詢
      }
    }
  }
}

也可以設(shè)置只關(guān)閉當(dāng)前模型的關(guān)聯(lián)關(guān)系,如:

export default class extends think.model.relation {
  init(..args){
    super.init(...args);
    this.relation = {
      user: {
        type: think.model.BELONG_TO,
        relation: "info" //關(guān)聯(lián)表 user 查詢時(shí)關(guān)閉對(duì) info 模型的關(guān)聯(lián)關(guān)系
      }
    }
  }
}

臨時(shí)關(guān)閉關(guān)聯(lián)關(guān)系

設(shè)置關(guān)聯(lián)關(guān)系后,查詢等操作都會(huì)自動(dòng)查詢關(guān)聯(lián)表的數(shù)據(jù)。如果某些情況下不需要查詢關(guān)聯(lián)表的數(shù)據(jù),可以通過 setRelation 方法臨時(shí)關(guān)閉關(guān)聯(lián)關(guān)系查詢。

全部關(guān)閉

通過 setRelation(false) 關(guān)閉所有的關(guān)聯(lián)關(guān)系查詢。

export default class extends think.model.relation {
  init(...args){
    super.init(...args);
    this.relation = {
      comment: think.model.HAS_MANY,
      cate: think.model.MANY_TO_MANY
    }
  },
  getList(){
    return this.setRelation(false).select();
  }
}

部分啟用

通過 setRelation('comment') 只查詢 comment 的關(guān)聯(lián)數(shù)據(jù),不查詢其他的關(guān)聯(lián)關(guān)系數(shù)據(jù)。

export default class extends think.model.relation {
  init(...args){
    super.init(...args);
    this.relation = {
      comment: think.model.HAS_MANY,
      cate: think.model.MANY_TO_MANY
    }
  },
  getList2(){
    return this.setRelation("comment").select();
  }
}

部分關(guān)閉

通過 setRelation('comment', false) 關(guān)閉 comment 的關(guān)聯(lián)關(guān)系數(shù)據(jù)查詢。

export default class extends think.model.relation {
  init(...args){
    super.init(...args);
    this.relation = {
      comment: think.model.HAS_MANY,
      cate: think.model.MANY_TO_MANY
    }
  },
  getList2(){
    return this.setRelation("comment", false).select();
  }
}

重新全部啟用

通過 setRelation(true) 重新啟用所有的關(guān)聯(lián)關(guān)系數(shù)據(jù)查詢。

export default class extends think.model.relation {
  init(...args){
    super.init(...args);
    this.relation = {
      comment: think.model.HAS_MANY,
      cate: think.model.MANY_TO_MANY
    }
  },
  getList2(){
    return this.setRelation(true).select();
  }
}

mongo 關(guān)聯(lián)模型

該關(guān)聯(lián)模型不操作不適合 mongo 模型,mongo 的關(guān)聯(lián)模型請(qǐng)見https://docs.mongodb.org/manual/tutorial/model-embedded-one-to-one-relationships-between-documents/。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)