跳到主要内容

云数据库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))

在下文中我们详细解释每一个字段的作用和场景。

请求地址 url

https://[环境地域].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

可选项: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即可查询到后面的数据。

skipnextToken都可以进行查询翻页,但 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": "时间戳" // 时间戳
}