數(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ì)多可以通過命令 thinkjs model [name] --relation
來創(chuàng)建關(guān)聯(lián)模型。如:
thinkjs model home/post --relation
會(huì)創(chuàng)建模型文件 src/home/model/post.js
。
可以通過 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);
}
}
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) keyfKey
關(guān)聯(lián)表與只對(duì)應(yīng)的 keyfield
關(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è)置的 orderlimit
關(guān)聯(lián)表查詢時(shí)設(shè)置的 limitpage
關(guān)聯(lián)表查詢時(shí)設(shè)置的 pagerModel
多對(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
}
}
}
一對(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"
}
}, ...]
一對(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"
}
}, ...
]
一對(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ù)。
多對(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
}, ...]
}, ...]
如果 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)聯(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)系查詢。
通過 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();
}
}
通過 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();
}
}
該關(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/。
更多建議: