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 catename data field name, default is key, here is catekey 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.