Tables in database often related to other tables and need to be operated with related tables together. For example, an article can have category, tag, comment and author, and these information often store in other related tables.
ThinkJS supports relational model which can simplify these operations.
ThinkJS supports four relationships:
think.model.HAS_ONE
one to one modelthink.model.BELONG_TO
one to one belong tothink.model.HAS_MANY
one to manythink.model.MANY_TO_MANY
many to manyUse thinkjs model [name] --relation
to create relational model:
thinkjs model home/post --relation
This will create model file src/home/model/post.js
.
Use relation
property to set relationship:
export default class extends think.model.relation {
init(...args){
super.init(...args);
//use relation property to set relationship, can set many relationships
this.relation = {
cate: {},
comment: {}
};
}
}
You can also use ES7 syntax to define relation
property:
export default class extends think.model.relation {
//define relation property directly
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: ""
},
};
}
}
Each field's means:
type
type of relationmodel
model name of relation table, default is key
, here is cate
name
data field name, default is key, here is cate
key
related key of current modelfKey
related key of related tablefield
field used to query related table, fKey must be included if you set this fieldwhere
where condition used to query related tableorder
order used to query related tablelimit
limit used to query related tablepage
page used to query related tablerModel
related model name in many to many typerfKey
key in related table in many to many typeIf you just want to set related type without other fields, you can use this simple way:
export default class extends think.model.relation {
init(...args){
super.init(...args);
this.relation = {
cate: think.model.MANY_TO_MANY
};
}
}
One to one relation, means current table has one additional table.
Suppose curret model name is user
and related table model name is info
, then the default value of key
field in configuration is id
, and the default value of fKey
is user_id
.
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
info: think.model.HAS_ONE
};
}
}
Execute quering operation will get below data:
[
{
id: 1,
name: "111",
info: { // data from related table
user_id: 1,
desc: "info"
}
}, ...]
One to one relation, and one belong to another one, as opposed to HAS_ONE.
Suppose curret model name is info
and related table model name is user
, then the default value of key
field in configuration is user_id
, and the default value of fKey
is id
.
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
user: think.model.BELONG_TO
};
}
}
Execute quering operation will get below data:
[
{
id: 1,
user_id: 1,
desc: "info",
user: {
name: "thinkjs"
}
}, ...
]
One to many relation.
Suppose current model name is post
, related table model name is comment
, then the default value of key
field in configuration is id
and the default value of fKey
is 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
}
};
}
}
Execute quering operation will get below data:
[{
id: 1,
title: "first post",
content: "content",
comment: [{
id: 1,
post_id: 1,
name: "welefen",
content: "first comment"
}, ...]
}, ...]
If data in related table needs pagination, use page
parameter:
"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();
}
}
Besides using setRelation
, you can also pass in a function, this function will be executed during paramater mergin.
Many to many relation.
Suppose current model name is post
, related table model name is cate
, then we need a relationship table. The default value of rModel
and rfKey
fields in configuration are post_cate
and 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"
}
};
}
}
Quering results will be:
[{
id: 1,
title: "first post",
cate: [{
id: 1,
name: "cate1",
post_id: 1
}, ...]
}, ...]
Suppose we have two tables, one set the other as HAS_ONE and the other set this as BELONG_TO, this will cause cycle quering during quering and result to dead cycle.
You can set relation
field in config to close related quering and prevent dead cycle:
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
user: {
type: think.model.BELONG_TO,
relation: false //close related quering when query user
}
};
}
}
You can also only close current model's relationship:
export default class extends think.model.relation {
init(..args){
super.init(...args);
this.relation = {
user: {
type: think.model.BELONG_TO,
relation: "info" //close info model's relationship whey query user
}
};
}
}
After set relationship, operations like query will query related table automatically. If you don't want to query related table, just use setRelation
method to close relationship temporarily.
Use setRelation(false)
to close all relationship query.
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();
}
}
Use setRelation('comment')
to query data from comment
, other table won't be queied.
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();
}
}
Use setRelation('comment', false)
to close comment
quering.
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();
}
}
Use setRelation(true)
to reopen all related quering.
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();
}
}
This relational model doesn't work for mongo model, mongo relational model stays here https://docs.mongodb.org/manual/tutorial/model-embedded-one-to-one-relationships-between-documents/.
This doc stays at https://github.com/75team/www.thinkjs.org/tree/master/view/zh-cn/doc/2.0/model_relation.md.