The think.model.base
class inherit from think.base class.
export default class extends think.model.base {
getList(){
}
}
module.exports = think.model({
getList: function(){
}
})
The primary key of databse, defautl is id
.
Model name, default is current file name.
Suppose current file path is for/bar/app/home/model/user.js, then the model name is user
.
The Prefiex of table in database, default is think_
.
The name of data table, not contains prefiex name, default equals to model name.
The fields of data table, auto analyse the data table.
The indexes of data table, auto analyse the data table.
The readonly fields list, when data updated, these fields will not been updated.
Config, specify when instancing.
Handler of connect database.
Data of operation.
Options of operation.
name
{String} model nameoptions
{Object} confing optionsmodule
{String} module namereturn
{Object}Get instance of model, it can read cross module.
export default class extends think.model.base {
async getList(){
// get instance of user model
let instance = this.model('user');
let list = await instance.select();
let ids = list.map(item => {
return item.id;
});
let data = await this.where({id: ['IN', ids]}).select();
return data;
}
}
return
{string}Get the prefix of table.
return
{String}Get config key, use it when cache db handler.
return
{Object}Based on current config to get instance of db, if exist, return directly.
return
{String} model nameReturn directly if configed, or parse current file name.
return
{String} get table name, contains prefixGet table name, contains prefix.
key
{String} cache keytimeout
{Number} cache expire time, the unit is seconds.return
{this}Set cache config.
export default class extends think.model.base {
getList(){
return this.cache('getList', 1000).where({id: {'>': 100}}).select();
}
}
export default class extends think.model.base {
getList(){
return this.cache(1000).where({id: {'>': 100}}).select();
}
}
export default class extends think.model.base {
getList(){
return this.cache({
key: 'getList',
timeout: 1000,
type: 'file' // use file cache
}).where({id: {'>': 100}}).select();
}
}
offset
{Number} set the start position of query length
{Number} set the length of queryreturn
{this}Set the limit of query result.
export default class extends think.model.base {
getList(){
// query twenty data
return this.limit(20).where({id: {'>': 100}}).select();
}
}
export default class extends think.model.base {
getList(){
// start from position 100, query twenty data
return this.limit(100, 20).where({id: {'>': 100}}).select();
}
}
page
{Number} current page, start with onelistRows
{Number} number of per pagereturn
{this}Set query pagination data, convert to limit
data automatically.
export default class extends think.model.base {
getList(){
// query the second page data, ten data of per page.
return this.page(2, 10).where({id: {'>': 100}}).select();
}
}
where
{String | Object} where conditionreturn
{this}Set where query condition, it can set logic with method _logic
, default is AND
. Mulpty query with method __complex
.
Noatice
: 1. example below don't suit for mengo model.in mongo, seting where condition to seen in model.mongo. 2.where condition need to been validated in Logic, or maybe cause some bug.
export default class extends think.model.base {
where1(){
//SELECT * FROM `think_user`
return this.where().select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 )
return this.where({id: 10}).select();
}
where3(){
//SELECT * FROM `think_user` WHERE ( id = 10 OR id < 2 )
return this.where('id = 10 OR id < 2').select();
}
where4(){
//SELECT * FROM `think_user` WHERE ( `id` != 10 )
return this.where({id: ['!=', 10]}).select();
}
}
export default class extends think.model.base {
where1(){
//SELECT * FROM `think_user` where ( title IS NULL );
return this.where({title: null}).select();
}
where2(){
//SELECT * FROM `think_user` where ( title IS NOT NULL );
return this.where({title: ['!=', null]}).select();
}
}
ThinkJS will transfer field and value by default for security bugs. sometimes, if not want to transfer in some special case, you can use EXP way, like:
export default class extends think.model.base {
where1(){
//SELECT * FROM `think_user` WHERE ( (`name` ='name') )
return this.where({name: ['EXP', "=\"name\""]}).select();
}
}
export default class extends think.model.base {
where1(){
//SELECT * FROM `think_user` WHERE ( `title` NOT LIKE 'welefen' )
return this.where({title: ['NOTLIKE', 'welefen']}).select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( `title` LIKE '%welefen%' )
return this.where({title: ['like', '%welefen%']}).select();
}
//like mult-value
where3(){
//SELECT * FROM `think_user` WHERE ( (`title` LIKE 'welefen' OR `title` LIKE 'suredy') )
return this.where({title: ['like', ['welefen', 'suredy']]}).select();
}
// muti-field or relation like one value
where4(){
//SELECT * FROM `think_user` WHERE ( (`title` LIKE '%welefen%') OR (`content` LIKE '%welefen%') )
return this.where({'title|content': ['like', '%welefen%']}).select();
}
// muti-filed and relation like one value
where5(){
//SELECT * FROM `think_user` WHERE ( (`title` LIKE '%welefen%') AND (`content` LIKE '%welefen%') )
return this.where({'title&content': ['like', '%welefen%']}).select();
}
}
export default class extens think.model.base {
where1(){
//SELECT * FROM `think_user` WHERE ( `id` IN ('10','20') )
return this.where({id: ['IN', '10,20']}).select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( `id` IN (10,20) )
return this.where({id: ['IN', [10, 20]]}).select();
}
where3(){
//SELECT * FROM `think_user` WHERE ( `id` NOT IN (10,20) )
return this.where({id: ['NOTIN', [10, 20]]}).select();
}
}
export default class extens think.model.base {
where1(){
//SELECT * FROM `think_user` WHERE ( (`id` BETWEEN 1 AND 2) )
return this.where({id: ['BETWEEN', 1, 2]}).select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( (`id` BETWEEN '1' AND '2') )
return this.where({id: ['between', '1,2']}).select();
}
}
export default class extends think.model.base {
where1(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 ) AND ( `title` = 'www' )
return this.where({id: 10, title: "www"}).select();
}
// modify logic to OR
where2(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 ) OR ( `title` = 'www' )
return this.where({id: 10, title: "www", _logic: 'OR'}).select();
}
// modify logic to XOR
where2(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 ) XOR ( `title` = 'www' )
return this.where({id: 10, title: "www", _logic: 'XOR'}).select();
}
}
export default class extends think.model.base {
where1(){
//SELECT * FROM `think_user` WHERE ( `id` > 10 AND `id` < 20 )
return this.where({id: {'>': 10, '<': 20}}).select();
}
// modify logic to OR
where2(){
//SELECT * FROM `think_user` WHERE ( `id` < 10 OR `id` > 20 )
return this.where({id: {'<': 10, '>': 20, _logic: 'OR'}}).select()
}
}
export default class extends think.model.base {
where1(){
//SELECT * FROM `think_user` WHERE ( `title` = 'test' ) AND ( ( `id` IN (1,2,3) ) OR ( `content` = 'www' ) )
return this.where({
title: 'test',
_complex: {id: ['IN', [1, 2, 3]],
content: 'www',
_logic: 'or'
}
}).select()
}
}
field
{String | Array} set query field, can be string or arrayreturn
{this}Set query field.
export default class extends think.controller.base {
async indexAction(){
let model = this.model('user');
// set string need to query, in string way, use comma to split
let data = await model.field('name,title').select();
}
}
export default class extends think.controller.base {
// invoke sql function in field
async listAction(){
let model = this.model('user');
let data = await model.field('id, INSTR(\'30,35,31,\',id + \',\') as d').select();
}
}
export default class extends think.controller.base {
async indexAction(){
let model = this.model('user');
// set query string in array way
let data = await model.field(['name','title']).select();
}
}
field
{String | Array} reverse field, means query except this fieldreturn
{this}Set reverse field, it will filter this filed when querying, it support string way and array way.
table
{String} table wayhasPrefix
{Boolean} whether tabel has prefix or not, if table value contains space, then don't add prefix.return
{this}Set table name, which can named a SQL statement.
export default class extends think.model.base {
getList(){
return this.table('test', true).select();
}
}
export default class extends think.model.base {
async getList(){
let sql = await this.model('group').group('name').buildSql();
let data = await this.table(sql).select();
return data;
}
}
union
{String | Object} union query SQL or table nameall
{Boolean} Whether is UNION ALL way or notreturn
{this}Union query.
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` UNION (SELECT * FROM think_pic2)
return this.union('SELECT * FROM think_pic2').select();
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` UNION ALL (SELECT * FROM `think_pic2`)
return this.union({table: 'think_pic2'}, true).select();
}
}
join
{String | Object | Array} conbine statement, default is LEFT JOIN
return
{this}Conbine query, support string, array, object and so on.
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` LEFT JOIN think_cate ON think_group.cate_id=think_cate.id
return this.join('think_cate ON think_group.cate_id=think_cate.id').select();
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` LEFT JOIN think_cate ON think_group.cate_id=think_cate.id RIGHT JOIN think_tag ON think_group.tag_id=think_tag.id
return this.join([
'think_cate ON think_group.cate_id=think_cate.id',
'RIGHT JOIN think_tag ON think_group.tag_id=think_tag.id'
]).select();
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` INNER JOIN `think_cate` AS c ON think_user.`cate_id`=c.`id`
return this.join({
table: 'cate',
join: 'inner', //join way, contains left, right, inner three ways
as: 'c', // table alias name
on: ['cate_id', 'id'] //ON condition
}).select();
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM think_user AS a LEFT JOIN `think_cate` AS c ON a.`cate_id`=c.`id` LEFT JOIN `think_group_tag` AS d ON a.`id`=d.`group_id`
return this.alias('a').join({
table: 'cate',
join: 'left',
as: 'c',
on: ['cate_id', 'id']
}).join({
table: 'group_tag',
join: 'left',
as: 'd',
on: ['id', 'group_id']
}).select()
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` LEFT JOIN `think_cate` ON think_user.`id`=think_cate.`id` LEFT JOIN `think_group_tag` ON think_user.`id`=think_group_tag.`group_id`
return this.join({
cate: {
on: ['id', 'id']
},
group_tag: {
on: ['id', 'group_id']
}
}).select();
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM think_user AS a LEFT JOIN `think_cate` AS c ON a.`id`=c.`id` LEFT JOIN `think_group_tag` AS d ON a.`id`=d.`group_id`
return this.alias('a').join({
cate: {
join: 'left', // has left,right,inner three values
as: 'c',
on: ['id', 'id']
},
group_tag: {
join: 'left',
as: 'd',
on: ['id', 'group_id']
}
}).select()
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` LEFT JOIN `think_cate` ON think_user.`id`=think_cate.`id` LEFT JOIN `think_group_tag` ON think_user.`id`=think_group_tag.`group_id` LEFT JOIN `think_tag` ON (think_user.`id`=think_tag.`id` AND think_user.`title`=think_tag.`name`)
return this.join({
cate: {on: 'id, id'},
group_tag: {on: ['id', 'group_id']},
tag: {
on: { // multi-field's ON
id: 'id',
title: 'name'
}
}
}).select()
}
}
export default class extends think.model.base {
async getList(){
let sql = await this.model('group').buildSql();
//SELECT * FROM `think_user` LEFT JOIN ( SELECT * FROM `think_group` ) ON think_user.`gid`=( SELECT * FROM `think_group` ).`id`
return this.join({
table: sql,
on: ['gid', 'id']
}).select();
}
}
order
{String | Array | Object} sort orderreturn
{this}Set sort order.
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` ORDER BY id DESC, name ASC
return this.order('id DESC, name ASC').select();
}
getList1(){
//SELECT * FROM `think_user` ORDER BY count(num) DESC
return this.order('count(num) DESC').select();
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` ORDER BY id DESC,name ASC
return this.order(['id DESC', 'name ASC']).select();
}
}
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` ORDER BY `id` DESC,`name` ASC
return this.order({
id: 'DESC',
name: 'ASC'
}).select();
}
}
tableAlias
{String} table alias namereturn
{this}Set tabel alias name.
export default class extends think.model.base {
getList(){
//SELECT * FROM think_user AS a;
return this.alias('a').select();
}
}
having
{String} query string with havingreturn
{this}Set having query.
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` HAVING view_nums > 1000 AND view_nums < 2000
return this.having('view_nums > 1000 AND view_nums < 2000').select();
}
}
group
{String} group query fieldreturn
{this}Set group query.
export default class extends think.model.base {
getList(){
//SELECT * FROM `think_user` GROUP BY `name`
return this.group('name').select();
}
}
distinct
{String} distinct fieldreturn
{this}Distinct field
export default class extends think.model.base {
getList(){
//SELECT DISTINCT `name` FROM `think_user`
return this.distinct('name').select();
}
}
explain
{Boolean} Whether add explain execution or notreturn
{this}Whether add explain execution before SQL for performance of SQL or not.
Options for filter.
data
{Object | Array} data to operateFilter data.
data
{Object} data will addAdd before operate.
data
{Object} data will addAdd after data.
Delete after operation.
data
{Object} data will addUpdate before operation.
data
{Object} data will addUpdate after operation.
data
{Object} single data to queryreturn
{Object | Promise}After find
query operation.
data
[Array] data to queryreturn
{Array | Promise}After select
query operation.
data
{Object}The data which to added and updated.
options
{Object} Config operate options, like:
export default class extends think.model.base {
getList(){
return this.options({
where: 'id = 1',
limit: [10, 1]
}).select();
}
}
Close database connection, normally donot invoke directly.
table
{String} table namereturn
{Promise}Get table filed information, read from database directly.
return
{String}Get the last SQL statement.
return
{Promise}Make current query condition to generate a SQL statement.
oriOpts
{Object}extraOptions
{Object}return
{Promise}Options which are based on some conditions to parse current operation.
return
{Promise}Return value of pk
, returning is a Promise.
field
{String} the field name of data tablevalue
{Mixed}return
{Mixed}Based on filed type of data table to pase value.
data
{Object} data to pasereturn
{Object}Invoke paseType
to parse data.
data
{Object} data to addoptions
{Object} operate optionsreplace
{Boolean} whether is replace or notreturn
{Promise} return inserted IDadd one data.
data
{Object} data to addwhere
{Object} where conditionreturn
{Promise}When where condition didn't passed any data then to add data.
dataList
{Array} data list to addoptions
{Object} operate optionsreplace
{Boolean} is replace or notreturn
{Promise} return the inserted IDAdd many data in one time.
options
{Object} operate optionsreturn
{Promise} return affected rowDelete data.
data
{Object} data to updateoptions
{Object} operate optionsreturn
{Promise} return affected rowsUpdata data.
dataList
{Array} data to updateoptions
{Object} operate optionsreturn
{Promise}Update multi-data, dataList must contains value of primay key, it will set to update condition automatically.
field
{String} field namestep
{Number} add value, default is 1return
{Promise}Increase value of field.
field
{String} field namestep
{Number} decrease value, default is 1return
{Promise}Decrease value of field.
options
{Object} operate optionsreturn
{Promise} return one dataQuery one data, type of data is object, if there is not result, return {}
.
options
{Object} operate optionsreturn
{Promise} return multi-dataQuery many data, type of data is array, if there is not result, return []
.
options
{Object} operate optionspageFlag
{Boolean} if page number is illegal, true means changed to first page, false means changed to last page, default is no change.return
{Promise}Page query, normally need to use with page
, like:
export default class extends think.controller.base {
async listAction(){
let model = this.model('user');
let data = await model.page(this.get('page')).countSelect();
}
}
returned data structure like this below:
{
numsPerPage: 10, //每页显示的条数
currentPage: 1, //当前页
count: 100, //总条数
totalPages: 10, //总页数
data: [{ //当前页下的数据列表
name: "thinkjs",
email: "admin@thinkjs.org"
}, ...]
}
field
{String} field name, split with commaone
{Boolean | Number} the number of resultreturn
{Promise}Get value of specify field.
field
{String} field namereturn
{Promise} return the number of fieldsGet the number of fields.
field
{String} field namereturn
{Promise}Get the sum of field value
field
{String} field namereturn
{Promise}Get the minimum of field
field
{String} field namereturn
{Promise}Get the maximum of field
field
{String} field namereturn
{Promise}Get the avg of field
return
{Promise}Specify SQL statement to query.
return
{Promise}Execute SQL statement.
sql
{String} to parsed SQL statementreturn
{String}Paser SQL statement, invoke util.format
to parse SQL statement, and parse __TABLENAME__
of SQL statement to tabel name.
export default class extends think.model.base {
getSql(){
let sql = 'SELECT * FROM __GROUP__ WHERE id=%d';
sql = this.parseSql(sql, 10);
//sql is SELECT * FROM think_group WHERE id=10
}
}
return
{Promise}Start transaction.
return
{Promise}Commit transaction.
return
{Promise}rollback transaction.
fn
{Function} to executed functionreturn
{Promise}Use transaction to execute passed function, which must return Promise.
export default class extends think.model.base {
updateData(data){
return this.transaction(async () => {
let insertId = await this.add(data);
let result = await this.model('user_cate').add({user_id: insertId, cate_id: 100});
return result;
})
}
}