云数据库API
清林云 BaaS 云数据库 OneDB 作为底层承载所有环境的应用数据,拥有理论上无限的数据存储能力和极快的数据读写速度,保障整个清林云 BaaS 系统的数据稳定和安全。
本章节详细说明清林云 BaaS 系统的云数据库 OneDB API 格式,类似于应用 API 格式TypeAPI,有部分区别。
云数据库 OneDB API 主要用于集成原有业务和原有数据上云。
#
基本结构API 的基本 HTTP 结构如下:
#
API 示例以浏览器的 fetch 请求为例:
fetch("https://环境地域.baasapi.com/cdb", { "headers": { "content-type": "application/json", "envid": "你的环境ID", "keyid": "你的环境密匙ID", "Authorization": "(必选)由环境密匙密码构建的访问token" }, "method": "POST", "body": JSON.stringify({ appId: "user", // 必填 tableId: "User", // 必填 action: "get", // 必填 ids: {}, columns: {}, getColumns: [], engineIndex: '', orderType: 'desc', endIds: {}, rowsLimit: 100, filter: {}, condition: {}, updateType: '', skip: 0, getTotalCount: false, querys: [], sorters: [], nextToken: '', })}).then(res=>res.json()).then(data=>console.log(data)).catch(e=>console.log(e))
在下文中我们详细解释每一个字段的作用和场景。
#
请求地址 urlhttps://[环境地域].baasapi.com/cdb
其中[环境地域]
为你使用环境的地域代码,例如:https://cn-east-1.baasapi.com/cdb
。
地域代码可在控制台概览页面的环境上方看到。
以下为所有地域代码:
- 中国东部:cn-east-1
- 中国北部:cn-north-1
- 中国南部:cn-south-1
- 中国西部:cn-west-1
- 中国香港:cn-hk-1
- 美国西部:us-west-1
- 美国东部:us-east-1
- 英国:uk-1
- 新加坡:sg-1
- 澳大利亚:au-1
- 印度:in-1
另外专有云和私有云地域代码根据客户定制。
#
请求方法 method统一为POST
。
#
请求头 headers{ "headers": { "Content-Type": "application/json", "envid": "你的环境ID", "keyid": "你的环境密匙Id", "Authorization": "Bearer 云数据库jwtToken" }}
请求内容类型统一为 application/json
。
携带你的环境 ID 和密匙 ID。
注意此处Authorization
,需要使用上面环境密匙的密码去签名一个 jwtToken,设置签名的对象为:{identity:"cdb"}
,即身份为 cdb。最好加上一个过期时间,以防 token 不慎泄露造成影响。
JavaScript 示例:
const token = 'Bearer ' + jwt.sign( { identity: 'cdb', }, '环境密匙密码', { expiresIn: '1h' }, );
另外,需要前往应用市场 AppHub,安装云数据库应用(应用 ID:cdb),然后进入该环境的密匙管理界面,设置该密匙-分应用权限-选择云数据库应用,开通该密匙的应用权限后才可以访问云数据库 API。
示例:"Authorization": "Bearer eyJhbGVCJ9.eyJMzEwMjF9.mXM2b6yg"
(此处为删减 token,实际 token 要更长一些)
之所以流程稍微复杂,是因为访问云数据库的 token 权限比较高,必须保障一定的安全性。
基础安全:云数据库 API 地址必须为 HTTPS
第一重安全:确保访问云数据库 API 的 token 不暴露在公网,不放到前端代码中
第二重安全:能够访问云数据库 API 的环境密匙需单独开通该应用的权限
第三重安全:确保访问云数据库 API 的 token 有过期时间
第四重安全:如不慎泄露,请尽快取消该密匙的云数据库应用权限或删除该密匙
第五重安全:如不慎泄露并造成数据恶意删除,请联系客服进行数据恢复,该方法需要一定人力和时间,所以尽量在源头做好安全管控
#
请求内容 body{ "appId": "user", // 必填 "tableId": "User", // 必填 "action": "get", // 必填 "ids": {}, "columns": {}, "getColumns": [], "engineIndex": "", "orderType": "desc", "endIds": {}, "rowsLimit": 100, "filter": {}, "condition": {}, "updateType": "", "skip": 0, "getTotalCount": false, "querys": [], "sorters": [], "nextToken": ""}
appId
是需要操作数据库表的应用 ID;
tableId
是需要操作数据库表的 ID;
action
是需要操作数据库表的动作,有以下几种:
get
#
查询单个数据。
必填项:ids
即该条数据的所有 id,示例:
{ "ids": { "userId": "test", "postId": "one" }}
可选项:getColumns
查询该条数据的部分列,如果不填则默认返回该条数据的全部列,示例:
{ "getColumns": ["name", "title"]}
如果没有该条数据,则会返回null
。
getMany
#
查询多条数据。
必填项:ids
即查询范围的起始 id。
示例:
{ "ids": { "userId": "test", "postId": "CDB:tableMaxId" // 特殊值,代表最大 }}
必填项:endIds
即查询范围的终止 id。
示例:
{ "endIds": { "userId": "test", "postId": "CDB:tableMinId" // 特殊值,代表最小 }}
可选项:orderType
查询的排序方向,asc
为正序,即从小到大,desc
为倒序从大到小,默认为倒序,示例:
{ "orderType": "asc"}
可选项:rowsLimit
需要返回数据的数量,默认为 100,最大为 5000,示例:
{ "rowsLimit": 100}
可选项:filter
可以在返回的数据中进行一次过滤,减少不符合条件数据的网络传输,示例:
{ "filter": { "conditionList": [ { "column": "name", "symbol": "=", "value": "清林云" }, { "column": "title", "symbol": "=", "value": "BaaS" } ], "conditionLogical": "and" }}
conditionList
是过滤条件列表,可以有一个或多个过滤条件。过滤条件有三个值:
column
是需要过滤的字段名;
symbol
是字段的值和给定的值之间的比较运算符号,符号有:= != > >= < <=
,意思是等于 不等于 大于 大于等于 小于 小于等于
;
value
是需要比较的给定的值;
conditionLogical
是多个过滤条件的组合逻辑:
and
是默认值,即代表过滤后的数据要满足所有过滤条件;
not
代表过滤后的数据不会符合过滤条件,conditionList
只能有一个过滤条件;
or
代表过滤后的数据只符合过滤条件其中之一即可;
可选项:getColumns
查询所有数据的部分列,如果不填则默认返回数据的全部列,示例:
{ "getColumns": ["name", "title"]}
create
#
新增一条数据。
必填项:ids
即新增数据的所有 id。
示例:
{ "ids": { "userId": "test", "postId": "CDB:nanoId" // 特殊值,代表21位随机值,类似uuid }}
另外还有几个特殊值:
CDB:timeId
:即 13 位时间戳加 10 位随机值,适用于极其严格要求数据不重复的场景;
CDB:microsecondId
:当数据表的类型为 A 系列并且该字段类型为microsecondId
时使用,格式为时间戳+3 位唯一事务数字;
必填项:columns
即新增数据的所有列字段。
示例:
{ "columns": { "string1": "qqq", "int2": 2, "boolean3": true, "float4": 2.3 }}
可选项:condition
可以在新建数据时提前进行一次判断,示例:
{ "condition": { "type": "ignore" }}
类型有如下几种:
ignore
: 忽略判断,直接新建数据,如果原先有该 ID 的数据,则会覆盖;
exist
: 期待已存在该 ID 的数据,如果原先有该 ID 的数据,则会覆盖;
notExist
: 期待不存在该 ID 的数据,如果原先有该 ID 的数据,则会报错;
默认是ignore
。
update
#
更新一条数据。
必填项:ids
即更新数据的所有 id。
示例:
{ "ids": { "userId": "test", "postId": "postone" }}
必填项:columns
即需要更新数据的字段。
示例:
{ "columns": { "string1": "qqq", "int2": 2, "boolean3": true, "float4": 2.3 }}
可选项:condition
可以在新建数据时提前进行一次判断,示例:
{ "condition": { "type": "ignore", "conditionList": [ { "column": "name", "symbol": "=", "value": "清林云" }, { "column": "title", "symbol": "=", "value": "BaaS" } ], "conditionLogical": "and" }}
类型有如下几种:
ignore
: 忽略判断,直接更新数据,如果原先没有该 ID 的数据,则会新建;
exist
: 期待已存在该 ID 的数据,如果原先没有该 ID 的数据,则会报错;
notExist
: 期待不存在该 ID 的数据,如果原先有该 ID 的数据,则会报错;
默认是ignore
。
更新数据的条件判断多了个列判断,和filter
一样,具体可见getMany
。
delete
#
删除一条数据。
必填项:ids
即删除数据的所有 id。
示例:
{ "ids": { "userId": "test", "postId": "posttwo" }}
可选项:condition
可以在删除数据时提前进行一次判断,示例:
{ "condition": { "type": "ignore" }}
类型有如下几种:
ignore
: 忽略判断,直接删除数据,如果原先有该 ID 的数据,则会删除,没有也正常执行;
exist
: 期待已存在该 ID 的数据,如果原先没有该 ID 的数据,则会报错;
notExist
: 期待不存在该 ID 的数据,如果原先有该 ID 的数据,则会报错;
默认是ignore
。
search
#
可选项:querys
查询条件列表。查询条件由多个条件组合而成,满足条件的数据会返回,看如下示例:
{ "querys": [ { "queryType": "equal", // 精确查询 "column": "title", "value": "a" // 只有该列的值完全等于value时才可查到 }, { "queryType": "equalMany", // 多词精确查询 "column": "title", "value": ["b", "c"] // 列值满足一个即可 }, { "queryType": "match", // 匹配查询,用于text类型字段 "column": "title", // 要查询的列名 "value": "this is 米饭" // 该分词可查到包含 this 米 米饭 的数据 }, { "queryType": "matchPhrase", // 短语查询,用于text类型字段 "column": "title", "value": "爱吃米饭" // 可以查到 我爱吃米饭,查不到 爱吃楼下的米饭 }, { "queryType": "range", // 范围查询,用于int字段 "column": "title", "rangeFrom": 100, "rangeTo": 2000 }, { "queryType": "prefix", // 前缀查询 "column": "title", "value": "上海" // 可查到值为 上海市浦东新区 的数据 }, { "queryType": "constScore", // 相关性查询 "column": "title", "value": "查询值" }, { "queryType": "functionScore", // 因子相关性查询 "column": "title", "factor": "因子", "value": "查询值" }, { "queryType": "nested", // 嵌套查询,用于nested类型数据 "column": "title", "searchKey": "customKey", "searchValue": "someValue" }, { "queryType": "wildcard", // 通配符查询 "column": "title", "value": "上海市??区*街道" // (*)代表任意字符序列,问号(?)代表任意单个字符 }, { "queryType": "matchAll" // 所有行数查询或随机返回数据 }, { "queryType": "distance", // 距离查询 "column": "location", "centerPoint": "30.00,-90.22", // 中心点坐标,纬度在前,经度在后 "distance": 1200.5 // 和中心点的距离,单位:米 }, { "queryType": "distanceBounding", // 地理矩形范围查询 "column": "location", "topLeft": "30.20,-90.22", // 左上角坐标 "bottomRight": "30.00,-90.20" // 右下角坐标 }, { "queryType": "distancePolygon", // 地理多边形查询 "column": "location", "points": ["30.20,-90.22", "30.20,-90.22"] // 多边形端点坐标 }, { "queryType": "exist", // 列存在查询 "column": "title" // 该列的值不为空即可返回 } ]}
可选项:sorters
查询排序方式。先看示例:
{ "sorters": [ { "sorterType": "ids", "orderType": "asc" }, { "sorterType": "column", "orderType": "desc", "columnName": "title" }, { "sorterType": "union", "orderType": "desc" }, { "sorterType": "distance", "orderType": "desc", "columnName": "location", "points": ["0,0"] } ]}
排序方式可以有多个,会根据顺序依次排序。排序方式的字段解释如下:
sorterType
排序类型:- 值为
column
代表是以某个列排序,由columnName
决定; - 值为
ids
代表主键数据排序; - 值为
union
代表相关性排序,使用了 BM25 算法计算相关性; - 值为
distance
代表距离排序,计算列由columnName
决定,距离点由points
决定;
- 值为
columnName
排序列名orderType
值为asc
正序或desc
倒序,四种类型都需要该值,默认为倒序从大到小points
为排序距离点,格式为["0,0"]
如果设置只查询部分列,需要排序的列一定要包含在
getColumns
内。
可选项:rowsLimit
需要返回的数据量,默认为 20,最大为 100,示例:
{ "rowsLimit": 100}
可选项:getTotalCount
是否返回符合查询条件的数据总数,默认为false
,示例:
{ "getTotalCount": true}
可选项:skip
查询时从第几条数据开始,默认为 0,最大 5000,常用于查询多条数据时进行翻页的功能。
示例:
{ "skip": 0}
可选项:nextToken
查询翻页的信息。
当查询数据时,如果符合条件的数据有 200 条,一次最多只能查询 100 条,那么返回的数据中就会携带前 100 条数据和nextToken
信息,前端收到后如果需要翻页,查询第 100-200 条数据,那么加入nextToken
即可查询到后面的数据。
skip
和nextToken
都可以进行查询翻页,但 skip 有最大值,超过最大值时的翻页就需要nextToken
来处理。
示例:
{ "nextToken": "xxx"}
可选项:getColumns
查询所有数据的部分列,如果不填则默认返回数据的全部列,示例:
{ "getColumns": ["name", "title"]}
#
返回内容返回内容都是 JSON 格式,分别有成功和失败两种状态:
#
成功成功会返回数据:
// action: "get"{ "ids": "idsValue", "columns": "columnsValue"}
// action: "getMany"{ "data": [ { "ids": "idsValue", "columns": "columnsValue" } ], "nextId": { "ids": "idsValue" }}
// action: "create"{ "ids": "idsValue"}
// action: "update"{ "ids": "idsValue"}
// action: "update"// updateType: "increment"{ "columns": "columnsValue"}
// action: "delete"{ "success": true}
// action: "search"{ "data": [ { "ids": "idsValue", "columns": "columnsValue" } ], "nextToken": "xxx", "totalCounts": 100}
#
失败失败返回遵循最新的通用 HTTP 异常返回标准草案,但是更改了状态码 400 为 200,加入了errCode
项进行判断,因为在某些请求客户端下,400 状态会导致一些程序异常。
{ "errCode": "错误码", // 通常为 1,第三方服务则是第三方错误码,验证请求是否出错一般判断是否有errCode即可,如 if(res.errCode){错误处理} else {正常处理} "type": "错误的API", "title": "错误原因", "detail": "详细数据", "instance": "请求ID和客户端数据"}
其中,detail
是如下字段的 Json 字符串:
{ "envId": "环境ID", "keyId": "环境Key", "appId": "应用ID", "tableId": "表ID", "action": "执行动作"}
instance
是如下字段的 Json 字符串:
{ "requestId": "请求ID", // 如果出现莫名错误,向客服提交该项用于追踪bug "clientIP": "请求端IP地址", // 请求端IP地址 "referer": "请求来源", // 请求来源 "userAgent": "请求客户端", // 请求客户端 "date": "时间戳" // 时间戳}