# 關聯模型
[TOC=2,3]
數據庫中表經常會跟其他數據表有關聯,數據操作時需要連同關聯的表一起操作。如:一個博客文章會有分類、標簽、評論,以及屬于哪個用戶。
ThinkJS 中支持關聯模型,讓處理這類操作非常簡單。
## 支持的類型
關聯模型中支持常見的 4 類關聯關系。如:
* `think.model.HAS_ONE`?一對一模型
* `think.model.BELONG_TO`?一對一屬于
* `think.model.HAS_MANY`?一對多
* `think.model.MANY_TO_MANY`?多對多
## 創建關聯模型
可以通過命令?`thinkjs model [name] --relation`?來創建關聯模型。如:
~~~
thinkjs model home/post --relation
~~~
會創建模型文件?`src/home/model/post.js`。
## 指定關聯關系
可以通過?`relation`?屬性來指定關聯關系。如:
~~~
export default class extends think.model.relation {
init(...args){
super.init(...args);
//通過 relation 屬性指定關聯關系,可以指定多個關聯關系
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: ""
},
}
}
}
~~~
各個字段含義如下:
* `type`?關聯關系類型
* `model`?關聯表的模型名,默認為配置的 key,這里為?`cate`
* `name`?對應的數據字段名,默認為配置的 key,這里為?`cate`
* `key`?當前模型的關聯 key
* `fKey`?關聯表與只對應的 key
* `field`?關聯表查詢時設置的 field,如果需要設置,必須包含?`fKey`?對應的值
* `where`?關聯表查詢時設置的 where 條件
* `order`?關聯表查詢時設置的 order
* `limit`?關聯表查詢時設置的 limit
* `page`?關聯表查詢時設置的 page
* `rModel`?多對多下,對應的關聯關系模型名
* `rfKey`?多對多下,對應里的關系關系表對應的 key
如果只用設置關聯類型,不用設置其他字段信息,可以通過下面簡單的方式:
~~~
export default class extends think.model.relation {
init(...args){
super.init(...args);
this.relation = {
cate: think.model.MANY_TO_MANY
}
}
}
~~~
### HAS_ONE
一對一關聯,表示當前表含有一個附屬表。
假設當前表的模型名為?`user`,關聯表的模型名為?`info`,那么配置中字段?`key`?的默認值為?`id`,字段?`fKey`的默認值為?`user_id`。
~~~
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
info: think.model.HAS_ONE
}
}
}
~~~
執行查詢操作時,可以得到類似如下的數據:
~~~
[
{
id: 1,
name: "111",
info: { //關聯表里的數據信息
user_id: 1,
desc: "info"
}
}, ...]
~~~
### BELONG_TO
一對一關聯,屬于某個關聯表,和 HAS_ONE 是相反的關系。
假設當前模型名為?`info`,關聯表的模型名為?`user`,那么配置字段?`key`?的默認值為?`user_id`,配置字段`fKey`?的默認值為?`id`。
~~~
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
user: think.model.BELONG_TO
}
}
}
~~~
執行查詢操作時,可以得到類似下面的數據:
~~~
[
{
id: 1,
user_id: 1,
desc: "info",
user: {
name: "thinkjs"
}
}, ...
]
~~~
### HAS_MANY
一對多的關系。
加入當前模型名為?`post`,關聯表的模型名為?`comment`,那么配置字段?`key`?默認值為?`id`,配置字段?`fKey`?默認值為?`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
}
}
}
}
~~~
執行查詢數據時,可以得到類似下面的數據:
~~~
[{
id: 1,
title: "first post",
content: "content",
comment: [{
id: 1,
post_id: 1,
name: "welefen",
content: "first comment"
}, ...]
}, ...]
~~~
如果關聯表的數據需要分頁查詢,可以通過?`page`?參數進行,如:
~~~
"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`?來合并參數外,可以將參數設置為函數,合并參數時會自動執行該函數。
### MANY_TO_MANY
多對多關系。
假設當前模型名為?`post`,關聯模型名為?`cate`,那么需要一個對應的關聯關系表。配置字段?`rModel`?默認值為`post_cate`,配置字段?`rfKey`?默認值為?`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"
}
}
}
}
~~~
查詢出來的數據結構為:
~~~
[{
id: 1,
title: "first post",
cate: [{
id: 1,
name: "cate1",
post_id: 1
}, ...]
}, ...]
~~~
### 關聯死循環
如果 2 個關聯表,一個設置對方為 HAS_ONE,另一個設置對方為 BELONG_TO,這樣在查詢關聯表的數據時會將當前表又查詢了一遍,并且會再次查詢關聯表,最終導致死循環。
可以在配置里設置?`relation`?字段關閉關聯表的關聯查詢功能,從而避免死循環。如:
~~~
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
user: {
type: think.model.BELONG_TO,
relation: false //關聯表 user 查詢時關閉關聯查詢
}
}
}
}
~~~
也可以設置只關閉當前模型的關聯關系,如:
~~~
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
user: {
type: think.model.BELONG_TO,
relation: "info" //關聯表 user 查詢時關閉對 info 模型的關聯關系
}
}
}
}
~~~
## 臨時關閉關聯關系
設置關聯關系后,查詢等操作都會自動查詢關聯表的數據。如果某些情況下不需要查詢關聯表的數據,可以通過?`setRelation`?方法臨時關閉關聯關系查詢。
### 全部關閉
通過?`setRelation(false)`?關閉所有的關聯關系查詢。
~~~
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`?的關聯數據,不查詢其他的關聯關系數據。
~~~
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)`?關閉?`comment`?的關聯關系數據查詢。
~~~
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)`?重新啟用所有的關聯關系數據查詢。
~~~
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 關聯模型
該關聯模型不操作不適合 mongo 模型,mongo 的關聯模型請見[https://docs.mongodb.org/manual/tutorial/model-embedded-one-to-one-relationships-between-documents/](https://docs.mongodb.org/manual/tutorial/model-embedded-one-to-one-relationships-between-documents/)。
- 快速入門
- 介紹
- 創建項目
- 項目結構
- 代碼規范
- 升級指南
- 進階應用
- 模塊
- 控制器
- 視圖
- 配置
- 路由
- 模型
- 介紹
- 事務
- 關聯模型
- Mysql
- MongoDB
- SQLite
- Adapter
- 介紹
- Cache
- Session
- WebSocket
- Template
- 擴展功能
- thinkjs 命令
- 靜態資源訪問
- Middleware
- Service
- Cookie
- 錯誤處理
- 錯誤信息
- 數據校驗
- 國際化
- 路徑常量
- REST API
- 定時任務
- 線上部署
- 推薦模塊
- API
- think
- think.base
- think.http.base
- http
- controller
- rest controller
- model
- model.mongo
- middleware