# 模型
[TOC=2,3]
項目開發中,經常要操作數據庫,如:增刪改查等操作。模型就是為了方便操作數據庫進行的封裝,一個模型對應數據庫中的一個數據表。
目前支持的數據庫有:`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 語句時會自動轉換為 limit
* `group`, 用于對查詢的 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](https://thinkjs.org/zh-CN/doc/2.0/adapter_cache.html)。
* `timeout`?默認緩存時間。
* * *
模型中更多的操作方式請見相關的?[API -> model](https://thinkjs.org/zh-CN/doc/2.0/api_model.html)。
- 快速入門
- 介紹
- 創建項目
- 項目結構
- 代碼規范
- 升級指南
- 進階應用
- 模塊
- 控制器
- 視圖
- 配置
- 路由
- 模型
- 介紹
- 事務
- 關聯模型
- 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