API
#
基础概念#
Collection集合是一系列的文档集,通过 db.collection(name)
可以获取指定集合的引用,在集合上可以进行以下操作
类型 | 接口 | 说明 |
---|---|---|
写 | add | 新增文档(触发请求) |
计数 | count | 获取符合条件的文档条数 |
读 | get | 获取集合中的文档,如果有使用 where 语句定义查询条件,则会返回匹配结果集 (触发请求) |
引用 | doc | 获取对该集合中指定 id 的文档的引用 |
查询条件 | where | 通过指定条件筛选出匹配的文档,可搭配查询指令(eq, gt, in, ...)使用 |
skip | 跳过指定数量的文档,常用于分页,传入 offset | |
orderBy | 排序方式 | |
limit | 返回的结果集(文档数量)的限制,有默认值和上限值 | |
field | 指定需要返回的字段 |
查询及更新指令用于在 where
中指定字段需满足的条件,指令可通过 db.command
对象取得。
#
Record / Document文档是数据库集合中的一个存储单元,在云开发里是一个 json 对象。通过 db.collection(collectionName).doc(docId)
可以获取指定集合上指定 id 的文档的引用,在文档上可以进行以下操作
接口 | 说明 | |
---|---|---|
写 | set | 覆写文档 |
update | 局部更新文档(触发请求) | |
remove | 删除文档(触发请求) | |
读 | get | 获取文档(触发请求) |
#
Query Command查询指令,应用于构建查询条件。以下指令皆挂载在 db.command
下
类型 | 接口 | 说明 |
---|---|---|
比较运算 | eq | 字段 == |
neq | 字段 != | |
gt | 字段 > | |
gte | 字段 >= | |
lt | 字段 < | |
lte | 字段 <= | |
in | 字段值在数组里 | |
nin | 字段值不在数组里 | |
逻辑运算 | and | 表示需同时满足指定的所有条件 |
or | 表示需同时满足指定条件中的至少一个 |
#
Update Command更新指令,应用于构建更新操作。以下指令皆挂载在 db.command
下
类型 | 接口 | 说明 |
---|---|---|
更新指令 | set | 设定字段等于指定值 |
inc | 指示字段自增某个值 | |
mul | 指示字段自乘某个值 | |
remove | 删除某个字段 | |
push | 向数组尾部追加元素,支持传入单个元素或数组 | |
pop | 删除数组尾部元素 | |
shift | 删除数组头部元素。使用同 pop | |
unshift | 向数组头部添加元素,支持传入单个元素或数组。使用同 push |
#
获取数据库实例说明:不需要参数,返回数据库的实例
// 初始化const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
#
获取集合的引用说明:接受一个 name 参数,指定需引用的集合名称
// 获取 `user` 集合的引用const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})
const db = app.database()
const collection = db.collection("user")
#
查询指令#
准备工作新建集合 articles,并准备插入如下数据
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk");const app = tcb.init({});
const db = app.database();
exports.main = async (event, context) => { // 创建集合名为 articles 的集合 await db.createCollection("articles"); const res = await db.collection("articles").add({ \_openid: "luke-111111" }); return { id: res.id };};
#
eq表示字段等于某个值。eq
指令接受一个字面量 (literal),可以是 number
, boolean
, string
, object
, array
。
比如筛选出所有自己发表的文章,除了用传对象的方式:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const myOpenID = "luke-111111" const res = await db .collection("articles") .where({ _openid: myOpenID }) .get()
// 用指令的方式 const res1 = await db .collection("articles") .where({ _openid: _.eq(myOpenID) }) .get()
return { data: res.data, data1: res1.data }}
注意 eq
指令比对象的方式有更大的灵活性,可以用于表示字段等于某个对象的情况,比如:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { // 这种写法表示匹配 stat.publishYear == 2018 且 stat.language == 'zh-CN' const res = await db .collection("articles") .where({ stat: { publishYear: 2018, language: "zh-CN" } }) .get()
console.log(res.data) // 打印查询的文档数组
// 这种写法表示 stat 对象等于 { publishYear: 2018, language: 'zh-CN' } const res1 = await db .collection("articles") .where({ stat: _.eq({ publishYear: 2018, language: "zh-CN" }) }) .get()
console.log(res1.data) // 打印查询的文档数组}
#
neq字段不等于。neq
指令接受一个字面量 (literal),可以是 number
, boolean
, string
, object
, array
。
如筛选出品牌不为 X 的计算机:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { brand: _.neq("X") } }) .get()
console.log(res.data) // 打印查询的文档数组}
#
gt字段大于指定值。
如筛选出价格大于 2000 的计算机:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", price: _.gt(2000) }) .get()
console.log(res.data) // 打印查询的文档数组}
#
gte字段大于或等于指定值。
#
lt字段小于指定值。
#
lte字段小于或等于指定值。
#
in字段值在给定的数组中。
筛选出内存为 8g 或 16g 的计算机商品:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: _.in([8, 16]) } }) .get() console.log(res.data) // 打印查询的文档数组}
#
nin字段值不在给定的数组中。
筛选出内存不是 8g 或 16g 的计算机商品:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: _.nin([8, 16]) } }) .get() console.log(res.data) // 打印查询的文档数组}
#
and表示需同时满足指定的两个或以上的条件。
如筛选出内存大于 4g 小于 32g 的计算机商品:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { // 流式写法 const res = await db .collection("goods") .where({ category: "computer", type: { memory: _.gt(4).and(_.lt(32)) } }) .get()
console.log(res.data) // 打印查询的文档数组
// 前置写法 const res1 = await db .collection("goods") .where({ category: "computer", type: { memory: _.and(_.gt(4), _.lt(32)) } }) .get()
console.log(res1.data) // 打印查询的文档数组}
#
or表示需满足所有指定条件中的至少一个。如筛选出价格小于 4000 或在 6000-8000 之间的计算机:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { //流式写法: const res = await db .collection("goods") .where({ category: "computer", type: { price: _.lt(4000).or(_.gt(6000).and(_.lt(8000))) } }) .get() console.log(res.data) // 打印查询的文档数组
// 前置写法 const res1 = await db .collection("goods") .where({ category: "computer", type: { price: _.or(_.lt(4000), _.and(_.gt(6000), _.lt(8000))) } }) .get()
console.log(res1.data) // 打印查询的文档数组
// 如果要跨字段 “或” 操作:(如筛选出内存 8g 或 cpu 3.2 ghz 的计算机) const res2 = await db .collection("goods") .where( _.or( { type: { memory: _.gt(8) } }, { type: { cpu: 3.2 } } ) ) .get()
console.log(res2.data) // 打印查询的文档数组}
#
RegExp根据正则表达式进行筛选
例如下面可以筛选出 version
字段开头是 "数字+s" 的文档,并且忽略大小写:
// 云函数环境下示例代码const tcb = require('@cloudbase/node-sdk');const app = tcb.init({ env:'xxx'})const db = app.database()
exports.main = async (event, context) => { // 可以直接使用正则表达式 const res = await db.collection('articles').where({ version: /^\ds/i }).get()
console.log(res.data) // 打印查询的文档数组
// 或者 const res1 = await db.collection('articles').where({ version: new db.RegExp({ regexp: '^\\ds' // 正则表达式为 /^\ds/,转义后变成 '^\\ds' options: 'i' // i表示忽略大小写 }) }).get()
console.log(res1.data) // 打印查询的文档数组}
#
更新指令#
set描述:用于设定字段等于指定值。这种方法相比传入纯 JS 对象的好处是能够指定字段等于一个对象。
示例代码:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("photo") .doc("doc-id") .update({ data: { style: _.set({ color: "red", size: "large" }) } }) console.log(res.updated) // 打印更新成功的文档数量}
#
inc描述:用于指示字段自增某个值,这是个原子操作,使用这个操作指令而不是先读数据、再加、再写回的好处是:
备注:
- 原子性:多个用户同时写,对数据库来说都是将字段加一,不会有后来者覆写前者的情况
- 减少一次网络请求:不需先读再写
之后的 mul 指令同理。
示例代码:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("user") .where({ _openid: "my-open-id" }) .update({ count: { favorites: _.inc(1) } }) console.log(res.updated) // 打印更新成功的文档数量}
#
mul描述:用于指示字段自乘某个值。
#
remove更新指令。用于表示删除某个字段。如某人删除了自己一条商品评价中的评分:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db.collection("comments").doc("comment-id").update({ rating: _.remove() }) console.log(res.updated) // 打印更新成功的文档数量}
#
push向数组尾部追加元素,支持传入单个元素或数组
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("comments") .doc("comment-id") .update({ // users: _.push('aaa') users: _.push(["aaa", "bbb"]) }) console.log(res.updated) // 打印更新成功的文档数量}
#
pop删除数组尾部元素
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db.collection("comments").doc("comment-id").update({ users: _.pop() }) console.log(res.updated) // 打印更新成功的文档数量}
#
unshift向数组头部添加元素,支持传入单个元素或数组。使用同 push
#
shift删除数组头部元素。使用同 pop
#
构建查询条件支持 where()
、limit()
、skip()
、orderBy()
、get()
、update()
、field()
、count()
等操作。
只有当调用get()
、 update()
时才会真正发送请求。
#
where描述:设置过滤条件。where 可接收对象作为参数,表示筛选出拥有和传入对象相同的 key-value 的文档。
输入参数: 无
比如筛选出所有类型为计算机的、内存为 8g 的商品:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})
const db = app.database()
exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: 8 } }) .get() console.log(res.data) // 打印查询的文档数组}
如果要表达更复杂的查询,可使用高级查询指令,比如筛选出所有内存大于 8g 的计算机商品:
// 云函数环境下示例代码const tcb = require('@cloudbase/node-sdk');const app = tcb.init({ env:'xxx'})
const db = app.database();
const _ = db.command // 取指令
exports.main = async (event, context) => { const res = await db.collection('goods').where({ category: 'computer', type: { memory: _.gt(8), // 表示大于 8 } }).get() console.log(res.data) // 打印查询的文档数组
#
limit描述:指定查询结果集数量上限
输入参数:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | Integer | 是 | 限制展示的数值 |
使用示例
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const collection = db.collection("user") // 例 操作 user 集合
exports.main = async (event, context) => { const res = await collection.where({}).limit(1).get() console.log(res.data) // 打印查询的文档数组}
#
skip描述:指定查询返回结果时从指定序列后的结果开始返回,常用于分页 输入参数:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | Integer | 是 | 限制展示的数值 |
示例代码
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const collection = db.collection("user") // 例 操作 user 集合
exports.main = async (event, context) => { const res = await collection.where({}).skip(4).get() console.log(res.data) // 打印查询的文档数组}
#
field描述:指定返回结果中文档需返回的字段
输入参数:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | Object | 是 | 要过滤的字段,不返回传 false,返回传 true |
示例代码
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const collection = db.collection("user") // 例 操作 user 集合
exports.main = async (event, context) => { const res = await collection.where({}).field({ age: true }).get() console.log(res.data) // 打印查询的文档数组}
备注:field 方法接受一个必填对象用于指定需返回的字段,对象的各个 key 表示要返回或不要返回的字段,value 传入 true|false(或 1|0)表示要返回还是不要返回。
#
orderBy描述:指定查询排序条件
输入参数:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
field | String | 是 | 排序的字段 |
orderType | String | 是 | 排序的顺序,升序(asc) 或 降序(desc) |
备注:方法接受一个必填字符串参数 fieldName 用于定义需要排序的字段,一个字符串参数 order 定义排序顺序。order 只能取 asc 或 desc。
如果需要对嵌套字段排序,需要用 "点表示法" 连接嵌套字段,比如 style.color 表示字段 style 里的嵌套字段 color。
同时也支持按多个字段排序,多次调用 orderBy 即可,多字段排序时的顺序会按照 orderBy 调用顺序先后对多个字段排序
示例代码
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const collection = db.collection("user") // 例 操作 user 集合
exports.main = async (event, context) => { const res = await collection.where({}).orderBy("name", "asc").get() console.log(res.data) // 打印查询的文档数组}
#
options描述:数据库接口配置
输入参数:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
timeout | Number | 否 | SDK 请求超时时间设置, 默认 15000ms |
multiple | Boolean | 否 | 是否仅操作单个文档,update/delete 方法可用 |
示例代码
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const collection = db.collection("user") // 例 操作 user 集合
exports.main = async (event, context) => { // 更新单文档 const updateRes = await collection .where({ name: "luke" }) .options({ multiple: false }) .update({ name: "lake" })
console.log(res.updated === 1) // 更新文档数为1
// 删除单文档 const deleteRes = await collection .where({ name: "luke" }) .options({ multiple: false }) .remove()
console.log(res.deleted === 1) // 删除文档数为1
// 设置SDK单接口请求超时 const getRes = await collection .where({ name: "luke" }) .options({ timeout: 10000 }) .get() console.log(getRes)}
#
createCollection#
1. 接口描述接口功能:新增集合
接口声明:createCollection(collName): Promise<Object>
#
2. 输入参数参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | String | 是 | 集合名 |
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
requestId | String | 是 | 请求 ID |
message | String | 否 | 接口报错时的错误信息 |
code | String | 否 | 接口报错时的错误码 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})
const db = app.database()
exports.main = async (event, context) => { // 创建集合名为coll-name的集合 const res = await db.createCollection("coll-name")
if (!res.code) { // 创建成功 }}
#
add#
1. 接口描述接口功能:插入一条文档或文档数组
接口声明:collection.add(object: Array<Object> | Object): Promise<Object>
备注:set 方法也可以用来新增文档,请参看文档更新部分 set 方法
#
2. 输入参数参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | Array<Object> 或 Object | 是 | 可支持批量插入或插入单个文档,例 [{_id: '10001', 'name': 'Ben'}, {_id: '10002', 'name': 'Booker'}] 或 {_id: '10001', 'name': 'Ben'}, _id 非必填 |
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
code | String | 否 | 状态码,操作成功则不返回 |
message | String | 否 | 错误描述,操作成功不返回 |
requestId | String | 是 | 请求 ID |
id | String | 否 | 文档 ID,插入单文档成功则返回 |
ids | Array<String> | 否 | 文档 ID,批量插入文档成功则返回 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})
const db = app.database()const collection = db.collection("user") // 例 操作 user 集合
exports.main = async (event, context) => { // 创建集合名为coll-name的集合 const res = await collection.add({ name: "Ben" })
console.log(res.id) //打印新增的文档ID
const batchRes = await collection.add([{ name: "luke" }, { name: "jimmy" }]) console.log(batchRes.ids)}
#
get#
1. 接口描述接口功能:获取数据库查询结果
接口声明:get(): Promise<Object>
注:get()如不指定 limit 则默认取前 100 条数据,且最大取前 100 条数据。
#
2. 输入参数空
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述 |
data | Object | 否 | 操作成功返回查询结果 |
requestId | string | 是 | 请求序列号,用于错误排查 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: 8 } }) .count() console.log(res.data) // 打印查询的文档数组}
#
count#
1. 接口描述接口功能:获取数据库查询结果
接口声明:cout(): Promise<Object>
#
2. 输入参数空
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述 |
total | integer | 否 | 计数结果 |
requestId | string | 否 | 请求序列号,用于错误排查 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: 8 } }) .count() console.log(res.total) // 打印查询的文档数量}
#
remove#
1. 接口描述接口功能:删除一条文档
接口声明:remove(): Promise<Object>
#
2. 输入参数无
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述 |
deleted | integer | 否 | 删除的文档数量 |
requestId | string | 是 | 请求序列号,用于错误排查 |
#
4. 示例代码方式 1. 通过 指定文档 ID 删除
collection.doc(_id).remove()
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const res = await db.collection("articles").doc("xxx").remove()
console.log(res.deleted) // 打印删除的文档数量}
方式 2. 条件查找文档然后直接批量删除
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { // 删除字段a的值大于2的文档 const res = await db .collection("articles") .where({ a: _.gt(2) }) .remove()
console.log(res.deleted) // 打印删除的文档数量}
#
update / set#
1. 接口描述接口功能:更新文档
接口声明:
update(object: <Object>): Promise<Object>
set(object: <Object>): Promise<Object>
备注:update 和 set 都可以用来更新文档,区别是 set 方法在要更新的文档不存在时新增一个文档;而 update 方法什么也不会做,返回 updated 为 0
#
2. 输入参数字段 | 类型 | 必填 | 说明 |
---|---|---|---|
- | <Object> | 是 | 替换文档的定义 |
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述 |
updated | integer | 否 | 影响的文档数量 |
upsertedId | string | 否 | 插入的文档的 id |
requestId | string | 是 | 请求序列号,用于错误排查 |
#
4. 示例代码更新指定文档
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { // 更新单文档 const res = await db.collection("articles").doc("doc-id").update({ name: "Hey" })
console.log(res.updated) // 打印更新成功的文档数量
// 批量更新文档 const res1 = await db .collection("articles") .where({ name: _.eq("hey") }) .update({ age: 18 })
console.log(res1.updated) // 打印更新成功的文档数量}
更新文档,如果不存在则创建
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { // 更新单文档 const res = await db.collection("articles").doc("doc-id").set({ name: "Hey" }) console.log(res.upsertedId) // 打印插入的文档的id}
#
updateAndReturn#
1. 接口描述接口功能:更新文档并返回更新后数据
接口声明:
updateAndReturn(object: <Object>): Promise<Object>
tip
仅支持更新符合查询条件的第一条文档,并返回更新后的该文档
#
2. 输入参数字段 | 类型 | 必填 | 说明 |
---|---|---|---|
- | <Object> | 是 | 替换文档的定义 |
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述 |
updated | integer | 是 | 1 or 0,表示成功更新的文档数量 |
doc | object | 否 | 更新成功则返回更新后的文档 |
requestId | string | 是 | 请求序列号,用于错误排查 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { // 更新并返回更新后文档 const res = await db .collection("articles") .where({ name: _.eq("hey") }) .updateAndReturn({ age: 18 })
console.log(res.doc) // 打印更新后的文档}
#
GEO 地理位置注意:如果需要对类型为地理位置的字段进行搜索,一定要建立地理位置索引。
#
GEO 数据类型#
Point用于表示地理位置点,用经纬度唯一标记一个点,这是一个特殊的数据存储类型。
签名:Point(longitude: number, latitude: number)
示例:
new db.Geo.Point(longitude, latitude)
#
LineString用于表示地理路径,是由两个或者更多的 Point
组成的线段。
签名:LineString(points: Point[])
示例:
new db.Geo.LineString([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB) // ...])
#
Polygon用于表示地理上的一个多边形(有洞或无洞均可),它是由一个或多个闭环 LineString
组成的几何图形。
由一个环组成的 Polygon
是没有洞的多边形,由多个环组成的是有洞的多边形。对由多个环(LineString
)组成的多边形(Polygon
),第一个环是外环,所有其他环是内环(洞)。
签名:Polygon(lines: LineString[])
示例:
new db.Geo.Polygon([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ...])
#
MultiPoint用于表示多个点 Point
的集合。
签名:MultiPoint(points: Point[])
示例:
new db.Geo.MultiPoint([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB) // ...])
#
MultiLineString用于表示多个地理路径 LineString
的集合。
签名:MultiLineString(lines: LineString[])
示例:
new db.Geo.MultiLineString([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ...])
#
MultiPolygon用于表示多个地理多边形 Polygon
的集合。
签名:MultiPolygon(polygons: Polygon[])
示例:
new db.Geo.MultiPolygon([ new db.Geo.Polygon(...), new db.Geo.Polygon(...), // ...])
#
GEO 操作符#
geoNear按从近到远的顺序,找出字段值在给定点的附近的文档。
签名:
db.command.geoNear(options: IOptions)
interface IOptions { geometry: Point // 点的地理位置 maxDistance?: number // 选填,最大距离,米为单位 minDistance?: number // 选填,最小距离,米为单位}
示例:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { const res = await db .collection("user") .where({ location: db.command.geoNear({ geometry: new db.Geo.Point(lngA, latA), maxDistance: 1000, minDistance: 0 }) }) .get() console.log(res.data) // 打印查询的文档数组}
#
geoWithin找出字段值在指定 Polygon / MultiPolygon,或 centerSphere 内的文档,无排序
用法:
db.command.geoWithin(IOptions)
interface IOptions { geometry?: Polygon | MultiPolygon; // 多边形 centerSphere?: [Point, number]; // 圆形}
tip
centerSphere 用法仅在 2.3.1 以上版本支持
centerSphere 对应的值的定义是:[ 地理位置点, 半径 ]
半径需以弧度计,比如需要 10km 的半径,则用距离除以地球半径 6378.1km 得出的数字。
示例:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { // 一个闭合的多边形区域 const area1 = new Polygon([ new LineString([ new Point(lngA, latA), new Point(lngB, latB), new Point(lngC, latC), new Point(lngA, latA) ]) ])
// 搜索 location 字段在这个多边形区域中的 user const res1 = await db .collection("user") .where({ location: db.command.geoWithin({ geometry: area1 }) }) .get() console.log(res1.data) // 打印查询的文档数组
// centerSphere表示 const area2 = [new Point(-88, 30), 10 / 6378.1]
// 搜索 location 字段在这个圆形区域中的 user const res2 = await db .collection("user") .where({ location: db.command.geoWithin({ centerSphere: area2 }) }) .get() console.log(res2.data) // 打印查询的文档数组}
#
geoIntersects找出字段值和给定的地理位置图形相交的文档
签名:
db.command.geoIntersects(IOptions)
interface IOptions { geometry: | Point | LineString | MultiPoint | MultiLineString | Polygon | MultiPolygon; // 地理位置}
示例:
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()const _ = db.command
exports.main = async (event, context) => { // 一条路径 const line = new LineString([new Point(lngA, latA), new Point(lngB, latB)])
// 搜索 location 与这条路径相交的 user const res = await db .collection("user") .where({ location: db.command.geoIntersects({ geometry: line }) }) .get() console.log(res.data) // 打印查询的文档数组}
#
时间 DateDate 类型用于表示时间,精确到毫秒,可以用 JavaScript 内置 Date 对象创建。需要特别注意的是,用此方法创建的时间是客户端时间,不是服务端时间。如果需要使用服务端时间,应该用 API 中提供的 serverDate 对象来创建一个服务端当前时间的标记,当使用了 serverDate 对象的请求抵达服务端处理时,该字段会被转换成服务端当前的时间,更棒的是,我们在构造 serverDate 对象时还可通过传入一个有 offset 字段的对象来标记一个与当前服务端时间偏移 offset 毫秒的时间,这样我们就可以达到比如如下效果:指定一个字段为服务端时间往后一个小时。
那么当我们需要使用客户端时间时,存放 Date 对象和存放毫秒数是否是一样的效果呢?不是的,我们的数据库有针对日期类型的优化,建议大家使用时都用 Date 或 serverDate 构造时间对象。
//服务端当前时间new db.serverDate()
//服务端当前时间加1Snew db.serverDate({ offset: 1000})
#
ObjectId 类型为解决原生 Mongo 数据库导出数据至云开发数据库后,产生的 ObjectId 数据结构兼容问题,现支持 ObjectId 类型使用。
#
插入 ObjectId 类型值 & 查询const app = tcb.init()const db = app.database()
const collName = "db-test-oid-test"const collection = db.collection(collName)
const insertRes = await collection.add({ a: db.ObjectId({ id: "61642e2da293c008ac5e8690" })})
const getRes = await collection .where({ a: db.ObjectId({ id: "61642e2da293c008ac5e8690" }) }) .get()
console.log("getRes", getRes)
#
ObjectId 类型联表查询const app = tcb.init()const db = app.database()
const collName = "db-test-oid-test"const lookupCollName = "db-test-oid-test-lookup"const collection = db.collection(collName)const lookupCollection = db.collection(lookupCollName)const objId1 = "61642e2da293c008ac5e868f"const objId2 = "61642e2da293c008ac5e8690"const addRes = await collection.add({ _id: db.ObjectId({ id: objId1 }), inviter_uid: db.ObjectId({ id: objId2 }), name: "test"})console.log(addRes.id === objId1)
const addRes1 = await lookupCollection.add({ _id: db.ObjectId({ id: objId2 }), inviter_uid: db.ObjectId({ id: objId1 }), name: "test1"})console.log(addRes1.id === objId2)
const aggregateRes = await lookupCollection .aggregate() .lookup({ from: collName, localField: "inviter_uid", foreignField: "_id", as: "newTest" }) .end()console.log("aggregateRes", aggregateRes)/* { "requestId":"17c6f5463f2_8", "data":[ { "_id":"61642e2da293c008ac5e8690", // id2 "inviter_uid":"61642e2da293c008ac5e868f", // id1 "name":"test1", "newTest":[ { "_id":"61642e2da293c008ac5e868f", // id1 "inviter_uid":"61642e2da293c008ac5e8690", // id2 "name":"test" } ] } ] }*/
#
数据库事务#
startTransaction#
1. 接口描述接口功能:发起事务
接口声明:startTransaction(): Promise<Object>
#
2. 输入参数无
#
3. 返回结果参数 | 类型 | 必填 | 说明 |
---|---|---|---|
_id | string | 否 | 成功则返回事务 id |
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const transaction = await db.startTransaction() console.log(transaction._id) // 打印事务id}
#
commit#
1. 接口描述接口功能:提交事务
接口声明:commit(): Promise<Object>
#
2. 输入参数无
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
requestId | string | 是 | 请求 id |
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述, 操作成功则不返回 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const transaction = await db.startTransaction() await transaction.commit()}
#
get#
1. 接口描述接口功能:事务查询文档
接口声明:
doc().get(): Promise<Object>
单文档查询where().get(): Promise<Object>
条件查询
#
2. 输入参数无
#
3. 返回结果参数 | 类型 | 必填 | 说明 |
---|---|---|---|
data | <Array>.Object or Object | 否 | 操作成功,条件查询时返回文档对象数组,单文档查询时返回单个文档对象 |
requestId | string | 是 | 请求 id |
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述, 操作成功则不返回 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { /** * 事务操作支持两种写法,写法一如下,1. 调用startTransaction发起事务 2. 事务操作 3.调用commitTransactio提交事务 * * */ const transaction = await db.startTransaction() const doc = await transaction.collection(collectionName).doc("docId").get() console.log(doc.data) // 打印查询的文档 await transaction.commit()
/** * 写法二,runTransaction(callback(transaction)), 支持用户传入回调,回调参数为transaction * * */ await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("docId").get() console.log(doc.data) // 打印查询的文档 })}
// 云函数下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { // 事务条件查询 const transaction = await db.startTransaction() const res = await transaction .collection(collectionName) .where({ name: "luke" }) .get() console.log(res.data) // 打印查询的文档 await transaction.commit()}
#
add#
1. 接口描述接口功能:事务插入文档
接口声明:add(data): Promise<Object>
#
2. 输入参数参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | <Array>.Object or Object | 是 | 插入单文档: 例 {_id: '10001', 'name': 'Ben'} _id 非必填 ,插入多文档 ['name': 'Ben'}, {'name': 'luke'}] |
#
3. 返回结果参数 | 类型 | 必填 | 说明 |
---|---|---|---|
requestId | string | 是 | 请求 id |
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述, 操作成功则不返回 |
id | string | 否 | 插入单文档数据返回的 docId |
ids | string | 否 | 插入多文档数据返回的 docId 数组 |
inserted | number | 否 | 仅在单文档插入时,返回插入成功的条数 |
ok | number | 否 | 仅在单文档插入时,返回插入状态 1 表示成功 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const transaction = await db.startTransaction() // 插入单文档 const res = await transaction .collection(collectionName) .add({ category: "Web", tags: ["JavaScript", "C#"], date }) console.log(res.id) // 打印添加的docId
// 插入多文档 const batchRes = await transaction.collection(collectionName).add([ { category: "Web", tags: ["JavaScript", "C#"], date }, { category: "Backend", tags: ["Java"], date } ]) console.log(batchRes.ids) // 打印添加的docId数组 await transaction.commit()}
#
update / set#
1. 接口描述接口功能:事务更新文档(仅支持单文档)
接口声明:
update(data): Promise<Object>
set(object: Object): Promise<Object>
备注:update 和 set 都可以用来更新文档,区别是 set 方法在要更新的文档不存在时新增一个文档;而 update 方法什么也不会做,返回 updated 为 0
#
2. 输入参数参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | Object | 是 | 要更新的字段对象 |
#
3. 返回结果参数 | 类型 | 必填 | 说明 |
---|---|---|---|
updated | number | 否 | 更新成功的条数 |
upserted | number | 否 | 插入成功的条数 |
requestId | string | 是 | 请求 id |
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述, 操作成功则不返回 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const transaction = await db.startTransaction() // update const updateResult = await transaction .collection(collectionName) .doc("docId") .update({ category: "Node.js", date })
console.log(updateResult.updated) // 更新的条数
// set const setResult = await transaction .collection(collectionName) .doc("docId") .set({ category: "Node.js", date })
console.log(setResult.updated, setResult.upserted) await transaction.commit()}
#
updateAndReturn#
1. 接口描述接口功能:事务更新并返回文档
接口声明:
updateAndReturn(data): Promise<Object>
tip
仅支持更新符合查询条件的第一条文档,并返回更新后的该文档
#
2. 输入参数参数 | 类型 | 必填 | 说明 |
---|---|---|---|
- | Object | 是 | 要更新的字段对象 |
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述 |
updated | integer | 是 | 1 or 0,表示成功更新的文档数量 |
doc | object | 否 | 更新成功则返回更新后的文档 |
requestId | string | 是 | 请求序列号,用于错误排查 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const updateResult = await transaction .collection(collectionName) .where({ name: "goreliu" }) .updateAndReturn({ age: 18 })
console.log(updateResult.updated, updateResult.doc) await transaction.commit()}
#
delete#
1. 接口描述接口功能:事务删除文档(仅支持单文档)
接口声明:delete(): Promise<Object>
#
2. 输入参数无
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
deleted | number | 否 | 删除成功的条数 |
requestId | string | 是 | 请求 id |
code | string | 否 | 状态码,操作成功则不返回 |
message | string | 否 | 错误描述, 操作成功则不返回 |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { // deletaDocument const transaction = await db.startTransaction() const deleteResult = await transaction .collection(collectionName) .doc("docId") .delete() console.log(deleteResult.deleted) // 删除成功的条数 await transaction.commit()}
#
rollback#
1. 接口描述接口功能:事务回滚
接口声明:rollback(): Promise<Object>
#
2. 输入参数无
#
3. 返回结果字段 | 类型 | 必填 | 说明 |
---|---|---|---|
requestId | string | 是 | 请求 id |
#
4. 示例代码// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { // 云函数环境下,下面代码放置入口函数体内 const transaction = await db.startTransaction() const doc = await transaction.collection(collectionName).doc("docId").get() console.log(doc.data) await transaction.rollback()}
#
runTransaction 使用说明- 支持自定义返回 (正常 return 或 throw error)
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { const result = await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) return "luke" })}
// result === 'luke'
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { try { await db.runTransaction(async (transaction) => { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) // mock 事务冲突 throw { code: "DATABASE_TRANSACTION_CONFLICT", message: "[ResourceUnavailable.TransactionConflict] Transaction is conflict, maybe resource operated by others. Please check your request, but if the problem persists, contact us." } }) } catch (e) { // e.code === 'DATABASE_TRANSACTION_CONFLICT' }}
- rollback 使用
// 云函数环境下示例代码const tcb = require("@cloudbase/node-sdk")const app = tcb.init({ env: "xxx"})const db = app.database()
exports.main = async (event, context) => { try { await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) await transaction.rollback("luke") }) } catch (err) { // err === 'luke' }
try { await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) await transaction.rollback() }) } catch (err) { // assert(err.requestId) console.log(err.requestId) // 默认rollback返回回滚的requestId }}
#
事务注意事项事务中进行并发操作时(如 Promise.all 触发数据库请求),容易引起冲突,请尽量使用串行方式触发请求。