# 关联模型
[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