15.4.2 Dbrest数据服务
dbrest是一个独立的、高性能的Web服务,通过其提供的REST API,可直接访问后端数据库。
使用dbrest服务,开发者只要了解RESTful,即使不会SQL语句,也可以操作数据库中的数据,从而帮助开发者从繁琐枯燥的CRUD编程中解脱出来,大大提高开发效率,让开发者有更多的精力投入到业务逻辑开发中。
dbrest遵循标准的RESTful设计风格:
l GET:查询数据
l POST:新增数据
l PUT:修改数据
l DELETE:删除数据
1、数据查询API
dbrest支持表查询和视图查询,查询结果以JSON数组的形式返回到Response Body中,Response header中的Content-Range代表本次返回数据的区间与记录总数,例如:
l */30,表示查询所有数据,共有30条符合条件的记录。
l 0-9/30,表示本次返回的数据的区间为0-9(分页查询,每页显示10条记录,当前在第一页),共有30条符合条件的记录。
(1)表或视图查询
当前用户权限范围内的所有表和视图均可被dbrest的查询API访问,例如返回poeple表的全部内容:
(2)行过滤
可以在字段上添加条件来过滤查询结果,每个查询参数代表一个查询条件。
l 一个参数,例如:返回年龄在18岁以下的人员:
GET /dbrest/people?age=lt.18 HTTP/1.1
l 连接多个参数,例如,返回年龄在25岁以下,并且身份是学生的人员:
GET /dbrest/people?age=lt.25&student=is.true HTTP/1.1
l 支持复杂逻辑,例如,返回年龄在18岁以下,或者身份是学生的人员:
GET /dbrest/people?age=lt.18&or.student=is.true HTTP/1.1
除了大于、小于、等于,查询条件支持如下10种操作符,见表15-4.
表15-4 操作符说明
操作符 |
含义 |
对应的SQL(PostgreSQL)操作符 |
eq |
等于 |
= |
gt |
大于 |
> |
gte |
大于等于 |
>= |
lt |
小于 |
< |
lte |
小于等于 |
<= |
neq |
不等于 |
< > 或 != |
like |
LIKE操作(需要使用*替换%) |
LIKE |
ilike |
ILIKE操作(需要使用*替换%) |
ILIKE |
in |
IN操作,如?age=in.14,16,18 |
IN |
is |
精确匹配(null,true,false) |
IS |
(3)列过滤
当某些列为大字段时,例如:text、bytea,对这些字段的查询将严重降低响应速度,可以在查询中使用select参数指定要查询的字段,屏蔽掉大字段,提高服务的吞吐量,避免出现性能问题。
GET /dbrest/people?select=id,name HTTP/1.1
(4)排序
可以使用order参数指定要排序的字段和排序方法
GET /dbrest/people?select=id,name,age&order=age HTTP/1.1
排序默认为正序,即order=age代表order=age.asc(按age字段做正序排序),如想执行倒排序,可指定排序方式为desc,如:order=age.desc
(5)分页查询
可在请求地址中指定limit和offset参数实现分页查询,其中limit参数代表每次获取的数据条数,offset为偏移量,例如:
l 每次查询10条记录,当前在第1页
GET /dbrest/people?limit=10&offset=0 HTTP/1.1
l 查询条件同上,当前在第2页
GET /dbrest/people?limit=10&offset=10 HTTP/1.1
(6)关联查询
如果想查询多个表的数据,可以先创建视图,将多个表的数据组织到一起,然后使用dbrest服务对视图进行查询,但该种方式需要开发人员了解SQL语句与视图的基本知识,有没有更简便的方法实现关联查询呢?答案是肯定的,那就是使用join参数实现关联查询。
GET /dbrest/people?join=people.grade_id.eq.grade.grade_id HTTP/1.1
该查询实现了people表和grade表的关联查询,用join参数指定了关联关系,关联字段为people表的grade_id字段和grade表的grade_id字段,查询结果包含了people和grade两个表的数据。
注:多个表之间的关联关系用英文逗号“, ”分隔。
(7)设置别名
关联查询时,可能会存在字段名重复的情况,例如上述的关联查询,如果people表和grade表都有grade_id字段,那查询结果中是不能出现两个grade_id的,为了解决该问题,可以使用as参数来设置查询字段的别名,避免结果集中出现名称重复的字段。
GET /dbrest/people?select=people.id,people.name,people.grade_id as student_grade_id,grade.grade_id as id_of_grade&join=people.grade_id.eq.grade.grade_id HTTP/1.1
(8)分组查询
可以使用groupby参数实现SQL中的分组查询功能,例如:
GET /dbrest/people?select=grade_id,count(*)&groupby=grade_id&having::count(*)=gte.1 HTTP/1.1
该命令返回的结果是按照grade_id字段分组统计people表的记录数,并且过滤记录数大于1的。count为SQL中的聚合函数,用来统计符合条件的记录数,可以使用的聚合函数有:
l count:统计记录数
l sum:计算合计数
l max:得到最大值
l min:得到最小值
l avg:得到平均值
2、数据新增API
新增数据使用HTTP POST方法,在url中指定要新增数据的表名称,请求体(Request Body)中是要新增的数据,数据格式为JSON,JSON的key为表的字段名称,value为需要插入到数据库中的值。
(1)单表插入
POST /dbrest/people HTTP/1.1
{ id: “p-001”, name: “Mike”, age: 16 }
(2)主从表插入
可以用一个命令同时向多个有关联的表插入数据,如下:
POST /dbrest/people HTTP/1.1
{
"student": true,
"grade_id": "1-1",
"name": "mike",
"id": "people-001",
"age": 18,
"people_class.id": {
"id": "data-001",
"people_id": "people-001",
"class_id": "class-001"
}
}
其中:people_class.id,people_class为关联表的名称,id为people_class的主键字段名称。从表数据可以传入多条,格式为JSON数组,如:[ {}, {} ]。
3、数据修改API
修改数据使用HTTP PUT方法,在url中指定要修改数据的表名称,请求体(Request Body)中是要新增的数据,数据格式为JSON,JSON的key为表的字段名称,value为需要更新到数据库中的值。
(1)单表修改
PUT /dbrest/people HTTP/1.1
{ id: “p-001”, name: “Mike”, age: 18 }
(2)主从表修改
PUT /dbrest/people?id=people-001 HTTP/1.1
{
"student": true,
"grade_id": "1-1",
"name": "mike",
"id": "people-001",
"age": 18,
"people_class.id": {
"id": "data-001",
"people_id": "people-001",
"class_id": "class-001"
}
}
其中:people_class.id,people_class为关联表的名称,id为people_class的主键字段名称。从表数据可以传入多条,格式为JSON数组,如:[ {}, {} ]。
4、数据删除API
删除数据使用HTTP DELETE方法,有两种删除模式:按条件删除与批量删除。
(1)按条件删除
DELETE /dbrest/people?id=eq.people-001 HTTP/1.1
其中:people为要删除的表名称,问号后为删除的条件。
(2)批量删除
按条件删除只能按照条件删除一个表的数据,如果想同时删除几个关联表的数据,需要使用批量删除命令:
POST /dbrest/delete HTTP/1.1
[{
"table": "table1的名称",
"table1主键字段名称": “要删除的主键值”
}, {
"table": "table2的名称",
"table2主键字段名称": “要删除的主键值”
}]