ThinkJS 模型介紹

2021-09-17 10:23 更新

模型

項目開發(fā)中,經(jīng)常要操作數(shù)據(jù)庫,如:增刪改查等操作。模型就是為了方便操作數(shù)據(jù)庫進行的封裝,一個模型對應(yīng)數(shù)據(jù)庫中的一個數(shù)據(jù)表。

目前支持的數(shù)據(jù)庫有:MysqlMongoDB 和 SQLite。

創(chuàng)建模型

可以在項目目錄下通過命令 thinkjs model [name] 來創(chuàng)建模型:

thinkjs model user;

執(zhí)行完成后,會創(chuàng)建文件 src/common/model/user.js。

默認情況下模型文件會創(chuàng)建在 common 模塊下,如果想創(chuàng)建在其他的模塊下,創(chuàng)建時需要指定模塊名:

thinkjs model home/user

模型配置

模型配置如下,可以在 src/common/config/db.js 中進行修改:

export default {
  type: "mysql", //數(shù)據(jù)庫類型
  host: "127.0.0.1", //數(shù)據(jù)庫 host
  port: "", //數(shù)據(jù)庫端口,默認為 3306
  name: "", //數(shù)據(jù)庫名
  user: "", //賬號
  pwd: "",  //密碼
  prefix: "think_", //數(shù)據(jù)表前綴,如果不想要數(shù)據(jù)表前綴,可以設(shè)置為空
  encoding: "utf8", //數(shù)據(jù)庫編碼
  nums_per_page: 10, //每頁顯示的條數(shù)
  log_sql: true, //是否記錄執(zhí)行的 sql 語句
  log_connect: true, //是否記錄數(shù)據(jù)庫連接信息
  cache: { // 數(shù)據(jù)庫查詢緩存配置
    on: true,
    type: "",
    timeout: 3600
  }
};

也可以在不同的模塊下進行不同的模型配置,此時需要設(shè)置模塊下對應(yīng)的模型配置,配置文件為src/[module]/config/db.js 。

數(shù)據(jù)表定義

默認情況下,模型名和數(shù)據(jù)表名都是一一對應(yīng)的。假設(shè)數(shù)據(jù)表前綴是 think_,那么 user 模型對應(yīng)的數(shù)據(jù)表為 think_user,user_group 模型對應(yīng)的數(shù)據(jù)表為 think_user_group。

如果需要修改,可以通過下面 2 個屬性進行:

  • tablePrefix 表前綴
  • tableName 表名,不包含前綴

ES6 方式

export default class extends think.model.base {
  init(...args){
    super.init(...args);
    this.tablePrefix = ""; //將數(shù)據(jù)表前綴設(shè)置為空
    this.tableName = "user2"; //將對應(yīng)的數(shù)據(jù)表名設(shè)置為 user2
  }
}

動態(tài)創(chuàng)建類方式

module.exports = think.model({
  tablePrefix: "", //直接通過屬性來設(shè)置表前綴和表名
  tableName: "user2",
  init: function(){
    this.super("init", arguments);
  }
})

模型實例化

模型實例化在不同的地方使用的方式有所差別,如果當前類含有 model 方法,那可以直接通過該方法實例化,如:

export default class extends think.controller.base {
  indexAction(){
    let model = this.model("user");
  }
}

否則可以通過調(diào)用 think.model 方法獲取實例化,如:

let getModelInstance = function(){
  let model = think.model("user", think.config("db"), "home");
}

使用 think.model 獲取模型的實例化時,需要帶上模型的配置。

鏈式調(diào)用

模型中提供了很多鏈式調(diào)用的方法(類似 jQuery 里的鏈式調(diào)用),通過鏈式調(diào)用方法可以方便的進行數(shù)據(jù)操作。鏈式調(diào)用是通過返回 this 來實現(xiàn)的。

export default class extends think.model.base {
  /**
   * 獲取列表數(shù)據(jù)
   */
  * getList(){
    let data = yield this.field("title, content").where({
      id: [">", 100]
    }).order("id DESC").select();
    ...
  }
}

模型中支持鏈式調(diào)用的方法有:

  • where, 用于查詢或者更新條件的定義
  • table, 用于定義要操作的數(shù)據(jù)表名稱
  • alias, 用于給當前數(shù)據(jù)表定義別名
  • data, 用于新增或者更新數(shù)據(jù)之前的數(shù)據(jù)對象賦值
  • field, 用于定義要查詢的字段,也支持字段排除
  • order, 用于對結(jié)果進行排序
  • limit, 用于限制查詢結(jié)果數(shù)據(jù)
  • page, 用于查詢分頁,生成 sql 語句時會自動轉(zhuǎn)換為 limit
  • group, 用于對查詢的 group 支持
  • having, 用于對查詢的 having 支持
  • join, 用于對查詢的 join 支持
  • union, 用于對查詢的 union 支持
  • distinct, 用于對查詢的 distinct 支持
  • cache 用于查詢緩存

CURD 操作

添加數(shù)據(jù)

添加一條數(shù)據(jù)

使用 add 方法可以添加一條數(shù)據(jù),返回值為插入數(shù)據(jù)的 id。如:

export default class extends think.controller.base {
  * addAction(){
    let model = this.model("user");
    let insertId = yield model.add({name: "xxx", pwd: "yyy"});
  }
}

添加多條數(shù)據(jù)

使用 addMany 方法可以添加一條數(shù)據(jù),如:

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

數(shù)據(jù)庫設(shè)計時,我們經(jīng)常需要把某個字段設(shè)為唯一,表示這個字段值不能重復(fù)。這樣添加數(shù)據(jù)的時候只能先去查詢下這個數(shù)據(jù)值是否存在,如果不存在才進行插入操作。

模型中提供了 thenAdd 方法簡化這一操作。

export default class extends think.controller.base {
  * addAction(){
    let model = this.model("user");
    //第一個參數(shù)為要添加的數(shù)據(jù),第二個參數(shù)為添加的條件,根據(jù)第二個參數(shù)的條件查詢無相關(guān)記錄時才會添加
    let result = yield model.thenAdd({name: "xxx", pwd: "yyy"}, {name: "xxx"});
    // result returns {id: 1000, type: "add"} or {id: 1000, type: "exist"}
  }
}

更新數(shù)據(jù)

更新數(shù)據(jù)使用 update 方法,返回值為影響的行數(shù)。如:

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"});
  }
}

查詢數(shù)據(jù)

模型中提供了多種方式來查詢數(shù)據(jù),如:查詢單條數(shù)據(jù),查詢多條數(shù)據(jù),讀取字段值,讀取最大值,讀取總條數(shù)等。

查詢單條數(shù)據(jù)

可以使用 find 方法查詢單條數(shù)據(jù),返回值為對象。如:

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", ...}
  }
}

如果數(shù)據(jù)表沒有對應(yīng)的數(shù)據(jù),那么返回值為空對象 {},可以通過 think.isEmpty 方法來判斷返回值是否為空。

查詢多條數(shù)據(jù)

可以使用 select 方法查詢多條數(shù)據(jù),返回值為數(shù)據(jù)。如:

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"}, ...]
  }
}

如果數(shù)據(jù)表中沒有對應(yīng)的數(shù)據(jù),那么返回值為空數(shù)組 [],可以通過 think.isEmpty 方法來判斷返回值是否為空。

分頁查詢數(shù)據(jù)

頁面中經(jīng)常遇到按分頁來展現(xiàn)某些數(shù)據(jù),這種情況下就需要先查詢總的條數(shù),然后在查詢當前分頁下的數(shù)據(jù)。查詢完數(shù)據(jù)后還要計算有多少頁。模型中提供了 countSelect 方法來方便這一操作,會自動進行總條數(shù)的查詢。

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, //每頁顯示的條數(shù)
  currentPage: 1, //當前頁
  count: 100, //總條數(shù)
  totalPages: 10, //總頁數(shù)
  data: [{ //當前頁下的數(shù)據(jù)列表
    name: "thinkjs",
    email: "admin@thinkjs.org"
  }, ...]
  }

如果傳遞的當前頁數(shù)超過了頁數(shù)范圍,可以通過傳遞參數(shù)進行修正。true 為修正到第一頁, false 為修正到最后一頁,即: countSelect(true) 或 countSelect(false)。

如果總條數(shù)無法直接查詢,可以將總條數(shù)作為參數(shù)傳遞進去,如: countSelect(1000),表示總條數(shù)有1000條。

刪除數(shù)據(jù)

可以使用 delete 方法來刪除數(shù)據(jù),返回值為影響的行數(shù)。如:

export default class extends think.controller.base {
  * deleteAction(){
    let model = this.model("user");
    let affectedRows = yield model.where({id: [">", 100]}).delete();
  }
}

查詢緩存

為了性能優(yōu)化,項目中經(jīng)常要對一些從數(shù)據(jù)庫中查詢的數(shù)據(jù)進行緩存。如果手工將查詢的數(shù)據(jù)進行緩存,勢必比較麻煩,模型中直接提供了 cache 方法來設(shè)置查詢緩存。如:

export default class extends think.model.base {
  getList(){
    //設(shè)定緩存 key 和緩存時間
    return this.cache("get_list", 3600).where({id: {">": 100}}).select();
  }
}

上面的代碼為對查詢結(jié)果進行緩存,如果已經(jīng)有了緩存,直接從緩存里讀取,沒有的話才從數(shù)據(jù)庫里查詢。緩存保存的 key 為 get_list,緩存時間為一個小時。

也可以不指定緩存 key,這樣會自動根據(jù) SQL 語句生成一個緩存 key。如:

export default class extends think.model.base {
  getList(){
    //只設(shè)定緩存時間
    return this.cache(3600).where({id: {">": 100}}).select();
  }
}

緩存配置

緩存配置為模型配置中的 cache 字段,如:

export default {
  cache: {
    on: true,
    type: "", 
    timeout: 3600
  }
}
  • on 數(shù)據(jù)庫緩存配置的總開關(guān),關(guān)閉后即使程序中調(diào)用 cache 方法也無效。
  • type 緩存配置類型,默認為內(nèi)存,支持的緩存類型請見 Adapter -> Cache。
  • timeout 默認緩存時間。

    • *

模型中更多的操作方式請見相關(guān)的 API -> model

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號