Model

原型方法

field(field, reverse)

设置要查询的字段。

  • field string | array 要查询的字段,可以是字符串,也可以是数组
  • reverse boolean 是否反选字段
  • return this
  1. // 生成的 sql 语句为,以下同:
  2. // SELECT * FROM `meinv_group`
  3. D('Group').field().select();
  4. // SELECT `id`,`title` FROM `meinv_group`
  5. D('Group').field('id, title').select();
  6. // SELECT `id`,`title` FROM `meinv_group`
  7. D('Group').field(['id', 'title']).select();
  8. // SELECT `cate_id`,`md5`,`width`,`height`,`pic_nums`,`view_nums`,`date` FROM `meinv_group`
  9. D('Group').field(['id', 'title'], true).select();

table(table, hasPrefix)

设置表名

  • table String 表名
  • hasPrefix Boolean 表名里是否已经含有了表前缀
  1. // 设置表名为 xxx
  2. D('Group').table('xxx').select();
  3. // 也可以将一条 sql 语句设置为表名
  4. D('Group').group('name').buildSql().then(function(sql){
  5. return D('Article').table(sql, true).select();
  6. }).then(function(data){
  7. })

limit(offset, length)

设置查询的数量。

  • offset 起始位置
  • length 查询的数目
  • return this
  1. // SELECT * FROM `meinv_group` LIMIT 10
  2. D('Group').limit(10).select();
  3. // SELECT * FROM `meinv_group` LIMIT 10,20
  4. D('Group').limit(10, 20).select();

page(page, listRows)

设置当前查询的页数,页数从 1 开始

  • page 当前的页数
  • listRows 一页多少条记录,默认值为 C('db_nums_per_page')
  • return this
  1. // SELECT * FROM `meinv_group`
  2. D('Group').page().select();
  3. // SELECT * FROM `meinv_group` LIMIT 0,20
  4. D('Group').page(1).select();
  5. // SELECT * FROM `meinv_group` LIMIT 10,10
  6. D('Group').page(2, 10).select();

union(union, all)

联合查询

  • union 联合查询的字符串
  • all 是否为 UNION ALL 模式
  • return this
  1. // SELECT * FROM `meinv_pic1` UNION (SELECT * FROM meinv_pic2)
  2. D('Pic1').union('SELECT * FROM meinv_pic2').select();
  3. // SELECT * FROM `meinv_pic1` UNION ALL (SELECT * FROM meinv_pic2)
  4. D('Pic1').union('SELECT * FROM meinv_pic2', true).select();
  5. // SELECT * FROM `meinv_pic1` UNION ALL (SELECT * FROM `meinv_pic2`)
  6. D('Pic1').union({table: 'meinv_pic2'}, true).select();
  7. // SELECT * FROM `meinv_pic1` UNION ALL (SELECT * FROM `meinv_pic2`) UNION (SELECT * FROM meinv_pic3)
  8. D('Pic1').union({table: 'meinv_pic2'}, true).union({table: 'meinv_pic3'}).select();

join(join)

组合查询

  • join 可以是字符串、数组、对象
  • return this
  1. // SELECT * FROM `meinv_group` LEFT JOIN meinv_cate ON meinv_group.cate_id=meinv_cate.id
  2. D('Group').join('meinv_cate ON meinv_group.cate_id=meinv_cate.id').select();
  3. // SELECT * FROM `meinv_group` LEFT JOIN meinv_cate ON meinv_group.cate_id=meinv_cate.id RIGHT JION meinv_tag ON meinv_group.tag_id=meinv_tag.id
  4. D('Group').join([
  5. 'meinv_cate ON meinv_group.cate_id=meinv_cate.id',
  6. 'RIGHT JOIN meinv_tag ON meinv_group.tag_id=meinv_tag.id'
  7. ]).select();
  8. // SELECT * FROM meinv_group INNER JOIN `meinv_cate` AS c ON meinv_group.`cate_id`=c.`id`
  9. D('Group').join({
  10. table: 'cate',
  11. join: 'inner', //join 方式,有 left, right, inner 3 种方式
  12. as: 'c', // 表别名
  13. on: ['cate_id', 'id'] //ON 条件
  14. }).select();
  15. // SELECT * FROM meinv_group AS a LEFT JOIN `meinv_cate` AS c ON a.`cate_id`=c.`id` LEFT JOIN `meinv_group_tag` AS d ON a.`id`=d.`group_id`
  16. D('Group').alias('a').join({
  17. table: 'cate',
  18. join: 'left',
  19. as: 'c',
  20. on: ['cate_id', 'id']
  21. }).join({
  22. table: 'group_tag',
  23. join: 'left',
  24. as: 'd',
  25. on: ['id', 'group_id']
  26. }).select()
  27. // SELECT * FROM meinv_group AS a LEFT JOIN `meinv_cate` AS c ON a.`id`=c.`id` LEFT JOIN `meinv_group_tag` AS d ON a.`id`=d.`group_id`
  28. D('Group').alias('a').join({
  29. cate: {
  30. join: 'left', // 有 left,right,inner 3 个值
  31. as: 'c',
  32. on: ['id', 'id']
  33. },
  34. group_tag: {
  35. join: 'left',
  36. as: 'd',
  37. on: ['id', 'group_id']
  38. }
  39. }).select()
  40. //SELECT * FROM `meinv_group` LEFT JOIN `meinv_cate` ON meinv_group.`id`=meinv_cate.`id` LEFT JOIN `meinv_group_tag` ON meinv_group.`id`=meinv_group_tag.`group_id`
  41. D('Group').join({
  42. cate: {
  43. on: ['id', 'id']
  44. },
  45. group_tag: {
  46. on: ['id', 'group_id']
  47. }
  48. }).select()
  49. //SELECT * FROM `meinv_group` LEFT JOIN `meinv_cate` ON meinv_group.`id`=meinv_cate.`id` LEFT JOIN `meinv_group_tag` ON meinv_group.`id`=meinv_group_tag.`group_id` LEFT JOIN `meinv_tag` ON (meinv_group.`id`=meinv_tag.`id` AND meinv_group.`title`=meinv_tag.`name`)
  50. D('Group').join({
  51. cate: {
  52. on: 'id, id'
  53. },
  54. group_tag: {
  55. on: ['id', 'group_id']
  56. },
  57. tag: {
  58. on: { // 多个字段的 ON
  59. id: 'id',
  60. title: 'name'
  61. }
  62. }
  63. }).select()
  64. // join 的 table 为 sql 语句
  65. // 这个方式推荐和 buildSql 结合使用,也可以单独使用
  66. // SELECT id as team_id,ta.team_name,ifnull(sum,0) as sum FROM ThinkJS_team AS ta LEFT JOIN (SELECT tt.id as team_id,`team_name`,`team_partin_year`,sum(IFNULL(invest_value,0)) as sum FROM ThinkJS_team AS tt LEFT JOIN `ThinkJS_invest` AS ti ON tt.`id`=ti.`invest_team_id` WHERE (invest_is_cancel = 0 or invest_is_cancel is null) GROUP BY tt.`id` HAVING team_partin_year=2014 ORDER BY `sum` desc ) AS temp ON ta.`id`=temp.`team_id` ORDER BY sum desc
  67. return D('team').alias('tt')
  68. .field('tt.id as team_id, team_name, team_partin_year, sum(IFNULL(invest_value, 0)) as sum')
  69. .join({
  70. table: 'invest',
  71. join: 'left',
  72. as: 'ti',
  73. on: ['tt.id', 'invest_team_id']
  74. })
  75. .where('invest_is_cancel = 0 or invest_is_cancel is null')
  76. .group('tt.id')
  77. .order({sum: 'desc'})
  78. .having('team_partin_year='+year).buildSql();}).then(function(sql){
  79. return D('team')
  80. .field('id as team_id, ta.team_name, ifnull(sum, 0) as sum')
  81. .alias('ta').join({
  82. table: sql,
  83. join: 'left',
  84. as: 'temp',
  85. on: ['id', 'temp.team_id']
  86. })
  87. .order('sum desc').select();});

order(order)

设置排序方式

  • order 排序方式,字符串
  • return this
  1. // SELECT * FROM `meinv_group` ORDER BY id
  2. D('Group').order('id').select();
  3. // SELECT * FROM `meinv_group` ORDER BY id DESC
  4. D('Group').order('id DESC').select();
  5. // SELECT * FROM `meinv_group` ORDER BY id DESC,title ASC
  6. D('Group').order('id DESC,title ASC').select();
  7. // SELECT * FROM `meinv_group` ORDER BY id ASC
  8. D('Group').order(['id ASC']).select();
  9. // SELECT * FROM `meinv_group` ORDER BY id ASC,title DESC
  10. D('Group').order(['id ASC', 'title DESC']).select()
  11. // SELECT * FROM `meinv_group` ORDER BY `id` ASC,`title` DESC
  12. D('Group').order({id: 'ASC', title: 'DESC'}).select()

alias(alias)

设置表别名

  • alaias 表别名,字符串
  • return this
  1. //SELECT * FROM meinv_group AS a
  2. D('Group').alias('a').select();

having(str)

having 查询

  • str having 查询的字符串
  • return this
  1. // SELECT * FROM `meinv_group` HAVING view_nums > 1000 AND view_nums < 2000
  2. D('Group').having('view_nums> 1000 AND view_nums <2000').select();

group(field)

分组查询

  • field 设定分组查询的字段
  • return this
  1. // SELECT * FROM `meinv_group` GROUP BY `view_nums`
  2. D('Group').group('view_nums').select();

distinct(field)

去重查询

  • field 去重的字段
  • return this
  1. // SELECT Distinct `view_nums` FROM `meinv_group`
  2. D('Group').distinct('view_nums').select();

where(where)

设置 where 条件

  • where 查询条件,可以是字符串、对象
  • return this

普通条件

  1. // SELECT * FROM `meinv_group`
  2. D('Group').where().select();
  3. // SELECT * FROM `meinv_group` WHERE (`id` = 10)
  4. D('Group').where({id: 10}).select();
  5. // 查询字符串
  6. // SELECT * FROM `meinv_group` WHERE id = 10 OR id < 2
  7. D('GROUP').where('id = 10 OR id < 2').select();
  8. // 操作符
  9. // SELECT * FROM `meinv_group` WHERE (`id` != 10)
  10. D('Group').where({id: ['!=', 10]}).select(); // 这里的操作符有> >= < <= !=

EXP 条件

ThinkJS 默认会对字段和值进行转义,防止安全漏洞。有时候一些特殊的情况不希望被转义,可以使用 EXP 的方式

  1. //SELECT * FROM `meinv_group` WHERE name='name'
  2. D('GROUP').where({name: ['EXP', "='name'"]});
  1. // 将 view_nums 字段值加 1
  2. D('GROUP').update({view_nums: ['EXP', 'view_nums+1']});

LIKE 条件

  1. // LIKE 和 NOT LIKE
  2. // SELECT * FROM `meinv_group` WHERE (`title` NOT LIKE 'welefen')
  3. D('Group').where({title: ['NOTLIKE', 'welefen']}).select();
  4. // SELECT * FROM `meinv_group` WHERE (`title` LIKE '%welefen%')
  5. D('Group').where({title: ['like', '%welefen%']}).select();
  6. //LIKE 多个值
  7. // SELECT * FROM `meinv_group` WHERE ((`title` LIKE 'welefen' OR `title` LIKE 'suredy') )
  8. D('Group').where({title: ['like', ['welefen', 'suredy']]}).select()
  9. // 多个字段 LIKE 同一个值,或的关系
  10. //SELECT * FROM `meinv_group` WHERE ((`title` LIKE '%welefen%') OR (`content` LIKE '%welefen%') )
  11. D('Group').where({'title|content': ['like', '%welefen%']}).select();
  12. // 多个字段 LIKE 同一个只,与的关系
  13. //SELECT * FROM `meinv_group` WHERE ((`title` LIKE '%welefen%') AND (`content` LIKE '%welefen%') )
  14. D('Group').where({'title&content': ['like', '%welefen%']}).select();

IN 条件

  1. //SELECT * FROM `meinv_group` WHERE (`id` IN ('10','20') )
  2. D('Group').where({id: ['IN', '10,20']}).select();
  3. //SELECT * FROM `meinv_group` WHERE (`id` IN (10,20) )
  4. D('Group').where({id: ['IN', [10, 20]]}).select();
  5. //SELECT * FROM `meinv_group` WHERE (`id` NOT IN (10,20) )
  6. D('Group').where({id: ['NOTIN', [10, 20]]}).select()

多字段查询

  1. //SELECT * FROM `meinv_group` WHERE (`id` = 10) AND (`title` = 'www')
  2. D('Group').where({id: 10, title: "www"}).select();
  3. // 修改为或的关系
  4. //SELECT * FROM `meinv_group` WHERE (`id` = 10) OR (`title` = 'www')
  5. D('Group').where({id: 10, title: "www", _logic: 'OR'}).select();
  6. // 修改为异或的关系
  7. //SELECT * FROM `meinv_group` WHERE (`id` = 10) XOR (`title` = 'www')
  8. D('Group').where({id: 10, title: "www", _logic: 'XOR'})

BETWEEN 查询

  1. //SELECT * FROM `meinv_group` WHERE ((`id` BETWEEN 1 AND 2) )
  2. D('Group').where({id: ['BETWEEN', 1, 2]}).select();
  3. //SELECT * FROM `meinv_group` WHERE ((`id` BETWEEN '1' AND '2') )
  4. D('Group').where({id: ['between', '1,2']}).select()

复合查询

  1. // SELECT * FROM `meinv_group` WHERE (`id`> 10 AND `id` <20)
  2. D('Group').where({
  3. id: {
  4. '>': 10,
  5. '<': 20
  6. }
  7. }).select()
  8. // SELECT * FROM `meinv_group` WHERE (`id` < 10 OR `id`> 20 )
  9. D('Group').where({
  10. id: {
  11. '<': 10,
  12. '>': 20,
  13. _logic: 'OR'
  14. }
  15. }).select()
  16. //SELECT * FROM `meinv_group` WHERE (`id`>= 10 AND `id` <= 20) OR (`title` LIKE '%welefen%') OR (`date`> '2014-08-12' )
  17. D('Group').where({
  18. id: {
  19. '>=': 10,
  20. '<=': 20
  21. },
  22. 'title': ['like', '%welefen%'],
  23. date: ['>', '2014-08-12'],
  24. _logic: 'OR'
  25. }).select();
  26. //SELECT * FROM `think_group` WHERE (`title` = 'test') AND ((`id` IN (1,2,3) ) OR (`content` = 'www') )
  27. D('Group').where({
  28. title: 'test',
  29. _complex: {id: ['IN', [1, 2, 3]],
  30. content: 'www',
  31. _logic: 'or'
  32. }
  33. }).select()

count(field)

查询符合条件的数目,可以有 where 条件

  • field count 的字段,默认会从数据表里查找主键的字段
  • return promise
  1. //SELECT COUNT(id) AS ThinkJS_count FROM `meinv_group` LIMIT 1
  2. D('Group').count('id').then(function(count){
  3. //count 为符合条件的数目
  4. });

sum(field)

对符合条件的字段值求和,可以有 where 条件

  • field 求和的字段
  • return promise
  1. //SELECT SUM(view_nums) AS ThinkJS_sum FROM `meinv_group` LIMIT 1
  2. D('Group').sum('view_nums').then(function(sum){
  3. //sum 为求和的值
  4. })

min(field)

求字段的最小值

  • field 要求最小值的字段
  • return promise
  1. //SELECT MIN(view_nums) AS ThinkJS_min FROM `meinv_group` LIMIT 1
  2. D('Group').min('view_nums').then(function(min){
  3. //min 为最小的 view_nums 值
  4. })

max(field)

求字段的最大值

  • field 要求最大值的字段
  • return promise
  1. //SELECT MAX(view_nums) AS ThinkJS_max FROM `meinv_group` LIMIT 1
  2. D('Group').max('view_nums').then(function(max){
  3. //max 为最小的 view_nums 值
  4. })

avg(field)

求字段的平均值

  • field 要求平均值的字段
  • return promise
  1. //SELECT AVG(view_nums) AS ThinkJS_avg FROM `meinv_group` LIMIT 1
  2. D('Group').avg('view_nums').then(function(avg){
  3. })

add(data)

插入数据

  • data 要插入的数据,对象
  • return promise
  1. var data = {
  2. title: 'xxx',
  3. content: 'yyy'
  4. };
  5. D('Group').add(data).then(function(insertId){
  6. // 如果插入成功,insertId 为插入的 id
  7. }).catch(function(err){
  8. // 插入失败,err 为具体的错误信息
  9. })

如果数据表中有字段设置为 unique,插入一个已经存在的值时就会报错。这种情况一般需要先按这个字段去查询下看有没有对应的记录,如果没有在进行插入。

为了简化开发者的使用,ThinkJS 提供了 thenAdd 方法。

thenAdd(data, where, returnDetail)

当数据表中不存在 where 条件对应的数据时,才进行插入。

  • data 要插入的数据
  • where 检测的条件
  • returnDetail 是否返回详细的信息
  1. // 假设数据表中字段 title 类型为 UNIQUE
  2. var data = {
  3. title: 'xxx',
  4. content: 'yyy'
  5. };
  6. var where = {title: 'xxx'}
  7. D('Group').thenAdd(data, where).then(function(id){
  8. //id 为已经存在的 id 或者刚插入的 id
  9. })
  10. // 返回详细的信息
  11. D('Group').thenAdd(data, where, true).then(function(data){
  12. //data 数据结构为
  13. data = {
  14. type: 'exist' || 'add', //exist 表示之前已经存在,add 表示新添加
  15. id: 111
  16. }
  17. })

使用场景:用户注册时就可以通过该方法来检查用户名或者邮箱已经存在。

addAll(data)

一次添加多条数据

  • data 要添加的数据,数组
  • return promise
  1. var data = [{title: 'xxx'}, {title: 'yyy'}];
  2. D('Group').addAll(data).then(function(insertId){
  3. // 插入成功
  4. }).catch(function(err){
  5. // 插入失败
  6. })

delete()

  • return promise

删除符合条件的数据

  1. // 删除所有数据
  2. D('Group').delete().then(function(affectedRows){
  3. //affectedRows 为影响的行数
  4. })
  5. // 删除 id 小于 100 的数据
  6. D('Group').where({id: ['<', 100]}).delete().then(function(affectedRows){
  7. //affectedRows 为影响的行数
  8. })

update(data)

更新符合条件的数据

  • data 要更新的数据
  • return promise
  1. // 将 id<10 的 title 设置为空
  2. D('Group').where({id: ['<', 10]}).update({title: ''})

select()

查询符合条件的数据

  • return promise
  1. D('Group').where({id: ['IN', [1, 2, 3]]}).select().then(function(data){
  2. //data 为数组
  3. // 如果查询数据为空,那么 data 为 []
  4. data = [{
  5. id: 1,
  6. title: '',
  7. ...
  8. },{
  9. id: 2,
  10. title: ''
  11. ...
  12. }
  13. ]
  14. })

find()

查找某一条符合条件的数据。

  • return promise
  1. // 查询 id=1000 的一条数据
  2. D('Group').where({id: 1000}).find().then(function(data){
  3. //data 为一个数据对象
  4. // 如果数据为空,那么 data 为 {}
  5. data = {
  6. id: 1000,
  7. title: 'xxx',
  8. ...
  9. }
  10. })

updateInc(field, step)

将字段值增加

  • field 要增加的字段
  • step 增加的数值,默认为 1
  • return promise
  1. // 将 id=10 的浏览数加 1
  2. D('Group').where({id: 10}).updateInc('view_nums').then(function(){
  3. })
  4. // 将 id=100 的浏览数加 10
  5. D('Group').where({id: 100}).updateInc('view_nums', 10).then(function(){
  6. })

updateDec(field, step)

将字段值减少

  • field 要减少的字段
  • step 减少的值,默认为 1
  • return promise
  1. // 将 id=10 的浏览数减 1
  2. D('Group').where({id: 10}).updateDec('view_nums').then(function(){
  3. })
  4. // 将 id=100 的浏览数减 10
  5. D('Group').where({id: 100}).updateDec('view_nums', 10).then(function(){
  6. })

getField(field, onlyOne)

获取某个字段的值。

  • field 要获取的字段,可以是一个字段,也可以是多个字段,多个字段用, 隔开
  • onlyOne 是否只需要一个值, true 或者数字
  • return promise
  1. // 取 id>5000 的集合,只需要 id 值,不需要其他字段值
  2. D('Group').where({id: ['>',5000]}).getField('id').then(function(data){
  3. //data 为一个数组
  4. data = [7565,7564,7563,7562,7561,7560,7559,7558,7557]
  5. })
  6. // 只需要 id>5000 的一个值
  7. D('Group').where({id: ['>', 5000]}).getField('id', true).then(function(data){
  8. //data 为数字
  9. data = 7557;
  10. })
  11. // 只需要 id>5000 的 3 值
  12. D('Group').where({id: ['>', 5000]}).getField('id', 3).then(function(data){
  13. //data 为数字
  14. data = [7559, 7558, 7557];
  15. })
  16. // 获取 id 和 view_nums 2 个字段的值
  17. D('Group').getField('id,view_nums').then(function(data){data = {"id":[7565,7564,7563,7562,7561,7560,7559,7558,7557],
  18. "view_nums":[1965,1558,2335,2013,1425,1433,1994,2035,1118]
  19. }
  20. })

countSelect(options, flag)

  • options 查询参数
  • flag 当分页值不合法的时候,处理情况。true 为修正到第一页,false 为修正到最后一页,默认不进行修正。
  • return promise
  1. // 按每页 20 条数据来展现文件
  2. D('Article').page(this.get("page"), 20).countSelect().then(function(data){
  3. //data 的数据格式为
  4. {
  5. count: 123, // 总条数
  6. total: 10, // 总页数
  7. page: 1, // 当前页
  8. num: 20, // 每页显示多少条
  9. data: [{}, {}] // 详细的数据
  10. }
  11. });
  12. //countSelect 里使用 group
  13. D('Article').page(10).group('name').countSelect().then(function(data){})
  14. //countSelect 里有子查询
  15. D('Group').group('name').buildSql().then(function(sql){
  16. return D('Artigle').table(sql, true).countSelect();
  17. }).then(function(data){})

buildSql(options)

将当前查询条件生成一个 SELECT 语句,可以用作子查询的 sql 语句。

  • options 操作选项
  • return promise
  1. D('Cate').where({id: ['>', 10]}).buildSql().then(function(sql){//sql = SELECT `id` FROM `meinv_cate` WHERE id> 10
  2. return D('GROUP').where({cate_id: ['IN', sql, 'exp']});
  3. })

query(sql, parse)

自定义 sql 语句进行查询,用于非常复杂的 sql 语句时使用。

  • sql 要执行的 sql 语句
  • parse 格式参数的数据
  • return promise
  1. var data = [
  2. value.field || '*',
  3. mapOptions.mapfKey,
  4. value.rTable || self.getRelationTableName(mapOptions.model),
  5. mapOptions.model.getTableName(),
  6. whereStr || 'WHERE',
  7. value.rfKey || (mapOptions.model.getModelName().toLowerCase() + '_id'),
  8. mapOptions.model.getPk(),
  9. value.where ? ('AND' + value.where) : ''
  10. ]
  11. D('Group').query('SELECT b.%s, a.%s FROM %s as a, %s as b %s AND a.%s=b.%s %s', data).then(function(data){
  12. // 查询的数据
  13. })

sql 语句中支持如下字符串的自动替换:

  • __TABLE__ 替换为当前模型里的表名
  • __USER__ 替换为 C('db_prefix') + 'user' 表,其他表类似
  1. // 解析后的 sql 为 SELECT * FROM meinv_group as a LEFT JOIN meinv_user as u ON a.id=u.id WHERE u.id > 10
  2. D('Group').query('SELECT * FROM __TABLE__ as a LEFT JOIN __USER__ as u ON a.id=u.id WHERE u.id> %d', 10);

execute(sql, parse)

自定义 sql 语句执行,用户复杂 sql 语句的情况。

使用方式与 query 相同,只是 then 里拿到的结果不同。exectue 为影响的行数。

close()

关闭当前数据库连接,非特殊条件下不要使用该方法。

startTrans()

开启事务

  • return Promise

commit()

提交事务

  • return Promise

rollback()

回滚事务

  • return Promise

事务操作 DEMO:

  1. var model = D('Group');
  2. // 开启事务
  3. model.startTrans().then(function(){
  4. return model.add(data);
  5. }).then(function(){
  6. return model.commit(); // 提交事务
  7. }).catch(function(){
  8. return model.rollback(); // 回滚事务
  9. })

注意:只有支持事务的存储引擎使用这 3 个方法才有效

静态方法

close()

关闭所有数据库连接。

  1. thinkRequire('Model').close();

数据库默认使用长连接的方式,不建议关闭数据库连接。该接口非特殊条件下,不要使用。