ThinkJS 模型介绍
模型
项目开发中,经常要操作数据库,如:增删改查等操作。模型就是为了方便操作数据库进行的封装,一个模型对应数据库中的一个数据表。
目前支持的数据库有:Mysql
,MongoDB
和 SQLite
。
创建模型
可以在项目目录下通过命令 thinkjs model [name]
来创建模型:
thinkjs model user;
执行完成后,会创建文件 src/common/model/user.js
。
默认情况下模型文件会创建在 common
模块下,如果想创建在其他的模块下,创建时需要指定模块名:
thinkjs model home/user
模型配置
模型配置如下,可以在 src/common/config/db.js
中进行修改:
export default {
type: "mysql", //数据库类型
host: "127.0.0.1", //数据库 host
port: "", //数据库端口,默认为 3306
name: "", //数据库名
user: "", //账号
pwd: "", //密码
prefix: "think_", //数据表前缀,如果不想要数据表前缀,可以设置为空
encoding: "utf8", //数据库编码
nums_per_page: 10, //每页显示的条数
log_sql: true, //是否记录执行的 sql 语句
log_connect: true, //是否记录数据库连接信息
cache: { // 数据库查询缓存配置
on: true,
type: "",
timeout: 3600
}
};
也可以在不同的模块下进行不同的模型配置,此时需要设置模块下对应的模型配置,配置文件为src/[module]/config/db.js
。
数据表定义
默认情况下,模型名和数据表名都是一一对应的。假设数据表前缀是 think_
,那么 user
模型对应的数据表为 think_user
,user_group
模型对应的数据表为 think_user_group
。
如果需要修改,可以通过下面 2 个属性进行:
tablePrefix
表前缀tableName
表名,不包含前缀
ES6 方式
export default class extends think.model.base {
init(...args){
super.init(...args);
this.tablePrefix = ""; //将数据表前缀设置为空
this.tableName = "user2"; //将对应的数据表名设置为 user2
}
}
动态创建类方式
module.exports = think.model({
tablePrefix: "", //直接通过属性来设置表前缀和表名
tableName: "user2",
init: function(){
this.super("init", arguments);
}
})
模型实例化
模型实例化在不同的地方使用的方式有所差别,如果当前类含有 model
方法,那可以直接通过该方法实例化,如:
export default class extends think.controller.base {
indexAction(){
let model = this.model("user");
}
}
否则可以通过调用 think.model
方法获取实例化,如:
let getModelInstance = function(){
let model = think.model("user", think.config("db"), "home");
}
使用 think.model
获取模型的实例化时,需要带上模型的配置。
链式调用
模型中提供了很多链式调用的方法(类似 jQuery 里的链式调用),通过链式调用方法可以方便的进行数据操作。链式调用是通过返回 this
来实现的。
export default class extends think.model.base {
/**
* 获取列表数据
*/
* getList(){
let data = yield this.field("title, content").where({
id: [">", 100]
}).order("id DESC").select();
...
}
}
模型中支持链式调用的方法有:
where
, 用于查询或者更新条件的定义table
, 用于定义要操作的数据表名称alias
, 用于给当前数据表定义别名data
, 用于新增或者更新数据之前的数据对象赋值field
, 用于定义要查询的字段,也支持字段排除order
, 用于对结果进行排序limit
, 用于限制查询结果数据page
, 用于查询分页,生成 sql 语句时会自动转换为 limitgroup
, 用于对查询的 group 支持having
, 用于对查询的 having 支持join
, 用于对查询的 join 支持union
, 用于对查询的 union 支持distinct
, 用于对查询的 distinct 支持cache
用于查询缓存
CURD 操作
添加数据
添加一条数据
使用 add
方法可以添加一条数据,返回值为插入数据的 id。如:
export default class extends think.controller.base {
* addAction(){
let model = this.model("user");
let insertId = yield model.add({name: "xxx", pwd: "yyy"});
}
}
添加多条数据
使用 addMany
方法可以添加一条数据,如:
export default class extends think.controller.base {
* addAction(){
let model = this.model("user");
let insertId = yield model.addMany([
{name: "xxx", pwd: "yyy"},
{name: "xxx1", pwd: "yyy1"}
]);
}
}
thenAdd
数据库设计时,我们经常需要把某个字段设为唯一,表示这个字段值不能重复。这样添加数据的时候只能先去查询下这个数据值是否存在,如果不存在才进行插入操作。
模型中提供了 thenAdd
方法简化这一操作。
export default class extends think.controller.base {
* addAction(){
let model = this.model("user");
//第一个参数为要添加的数据,第二个参数为添加的条件,根据第二个参数的条件查询无相关记录时才会添加
let result = yield model.thenAdd({name: "xxx", pwd: "yyy"}, {name: "xxx"});
// result returns {id: 1000, type: "add"} or {id: 1000, type: "exist"}
}
}
更新数据
更新数据使用 update
方法,返回值为影响的行数。如:
export default class extends think.controlle.base {
* updateAction(){
let model = this.model("user");
let affectedRows = yield model.where({name: "thinkjs"}).update({email: "admin@thinkjs.org"});
}
}
查询数据
模型中提供了多种方式来查询数据,如:查询单条数据,查询多条数据,读取字段值,读取最大值,读取总条数等。
查询单条数据
可以使用 find
方法查询单条数据,返回值为对象。如:
export default class extends think.controller.base {
* listAction(){
let model = this.model("user");
let data = yield model.where({name: "thinkjs"}).find();
//data returns {name: "thinkjs", email: "admin@thinkjs.org", ...}
}
}
如果数据表没有对应的数据,那么返回值为空对象 {}
,可以通过 think.isEmpty
方法来判断返回值是否为空。
查询多条数据
可以使用 select
方法查询多条数据,返回值为数据。如:
export default class extends think.controller.base {
* listAction(){
let model = this.model("user");
let data = yield model.limit(2).select();
//data returns [{name: "thinkjs", email: "admin@thinkjs.org"}, ...]
}
}
如果数据表中没有对应的数据,那么返回值为空数组 []
,可以通过 think.isEmpty
方法来判断返回值是否为空。
分页查询数据
页面中经常遇到按分页来展现某些数据,这种情况下就需要先查询总的条数,然后在查询当前分页下的数据。查询完数据后还要计算有多少页。模型中提供了 countSelect
方法来方便这一操作,会自动进行总条数的查询。
export default class extends think.controller.base {
* listAction(){
let model = this.model("user");
let data = yield model.page(this.get("page"), 10).countSelect();
}
}
返回值格式如下:
{
numsPerPage: 10, //每页显示的条数
currentPage: 1, //当前页
count: 100, //总条数
totalPages: 10, //总页数
data: [{ //当前页下的数据列表
name: "thinkjs",
email: "admin@thinkjs.org"
}, ...]
}
如果传递的当前页数超过了页数范围,可以通过传递参数进行修正。true
为修正到第一页, false
为修正到最后一页,即: countSelect(true)
或 countSelect(false)
。
如果总条数无法直接查询,可以将总条数作为参数传递进去,如: countSelect(1000)
,表示总条数有1000条。
删除数据
可以使用 delete
方法来删除数据,返回值为影响的行数。如:
export default class extends think.controller.base {
* deleteAction(){
let model = this.model("user");
let affectedRows = yield model.where({id: [">", 100]}).delete();
}
}
查询缓存
为了性能优化,项目中经常要对一些从数据库中查询的数据进行缓存。如果手工将查询的数据进行缓存,势必比较麻烦,模型中直接提供了 cache
方法来设置查询缓存。如:
export default class extends think.model.base {
getList(){
//设定缓存 key 和缓存时间
return this.cache("get_list", 3600).where({id: {">": 100}}).select();
}
}
上面的代码为对查询结果进行缓存,如果已经有了缓存,直接从缓存里读取,没有的话才从数据库里查询。缓存保存的 key 为 get_list
,缓存时间为一个小时。
也可以不指定缓存 key,这样会自动根据 SQL 语句生成一个缓存 key。如:
export default class extends think.model.base {
getList(){
//只设定缓存时间
return this.cache(3600).where({id: {">": 100}}).select();
}
}
缓存配置
缓存配置为模型配置中的 cache
字段,如:
export default {
cache: {
on: true,
type: "",
timeout: 3600
}
}
on
数据库缓存配置的总开关,关闭后即使程序中调用cache
方法也无效。type
缓存配置类型,默认为内存,支持的缓存类型请见 Adapter -> Cache。-
timeout
默认缓存时间。 -
- *
模型中更多的操作方式请见相关的 API -> model。
更多建议: