跳到主要内容

存储能力插件 SDK

ONES 提供插件存储能力

ONES 的实体存储 SDK 允许你使用各种查询条件查询存储在这些结构中的数据,或者对数据进行创建、更新、删除等数据管理操作。

目前支持的存储能力有:实体存储。

要求

ONES@ones-op/sdk@ones/cli
v6.31.0v1.0.8v1.40.10

实体存储 SDK

实体数据需要通过实体定义进行初始化。

以下示例,均以 demo 实体配置作为示例用法:

config/plugin.yaml
storage:
entities:
- name: employee # 员工实体
attributes:
name: # 员工名
type: string
length: 32
required: true
age: # 员工年龄
type: integer
required: true
deleted: # 是否删除标记
type: boolean
required: true
indexes:
- name: find_by_name # 以员工名作为范围查询的索引
range_attribute: name
- name: find_by_age_in_deleted_partition # 在删除标记的属性分区中,以员工年龄作为范围查询的索引
range_attribute: age
partition:
- deleted

SDK 使用预览

实体定义之后,你需要使用 Git,提交代码。

提交代码或者通过 op 命令打包插件时,均会校验 config/plugin.yaml 的实体声明格式。

如果格式正确,你在编码时,编辑器(Visual Studio Code)会提示你如何使用实体存储 SDK,以及它的实体数据类型。

创建或者更新一条实体数据

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee').set('employee001', {
name: 'Mike',
age: 25,
deleted: false,
})

创建或者更新实体数据的规范

实体数据的属性的类型需要满足实体定义的类型。

  • 如果 Key 不存在,则创建实体数据:
    • 必填属性,需要提供。
    • 声明默认值的属性,如果缺失,则会使用默认值创建该条实体数据。
  • 如果 Key 存在,则更新实体数据:
    • 必填属性,需要提供。
    • 声明默认值的属性,如果缺失,则保留原来的属性值不变。

批量创建或者更新实体数据

batchSet 接收一组数据,该组数据中,可以部分数据是创建,部分数据是更新。且每一条数据都需要符合:

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee').batchSet([
{
key: 'employee888',
value: {
name: 'Emma',
age: 24,
deleted: true,
},
},
{
key: 'employee222',
value: {
name: 'Neo',
age: 28,
deleted: false,
},
},
{
key: 'employee999',
value: {
name: 'Molly',
age: 30,
deleted: false,
},
},
])

删除一条实体数据

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee').delete('employee001')

批量删除实体数据

batchDelete 接收一组数据,且每一条数据都需要符合:

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee').batchDelete(['employee888', 'employee222'])

获取一条实体数据

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee')
.get('employee001')
.then((data) => {
// 获取实体
console.log(data)
// 获取员工名
console.log(data?.name)
// 获取员工年龄
console.log(data?.age)
// 获取删除标记
console.log(data?.deleted)
})

返回值类型

backend/src/index.ts
// 具体类型由定义的实体的类型决定
type data = {
name: string // 员工名
age: number // 员工年龄
deleted: boolean // 删除标记
}

使用实体查询对象

实体查询对象提供更多查询方式。

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee').query()

使用实体查询对象获取一条实体数据

  • 如果该实体不存在任何数据,则返回 undefined,SDK 不会抛出错误。

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee')
.query()
.getOne()
.then((data) => {
// 获取 Key
console.log(data?.key)
// 获取实体数据
console.log(data?.value)
// 获取员工名
console.log(data?.value.name)
// 获取员工年龄
console.log(data?.value.age)
// 获取删除标记
console.log(data?.value.deleted)
})

返回值类型

backend/src/index.ts
// 具体类型由定义的实体的类型决定
type data = {
key: string // Key
value: {
name: string // 员工名
age: number // 员工年龄
deleted: boolean // 删除标记
}
}

使用实体查询对象获取实体数据数组

  • 如果该实体不存在任何数据,则返回 空数组,SDK 不会抛出错误。

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee')
.query()
.getMany()
.then((data) => {
// 获取当前分页数据总数
console.log(data.page_info.count)
// 是否有更多数据
console.log(data.page_info.has_more)
// 获取当前分页末尾数据游标
console.log(data.page_info.end_cursor)
// 获取第一条数据的 Key
console.log(data.data[0].key)
// 获取第一条数据的实体数据
console.log(data.data[0].value)
})

返回值类型

backend/src/index.ts
// 具体类型由定义的实体的类型决定
type data = {
page_info: {
count: number // 当前分页数据总数
has_more: boolean // 是否有更多数据
end_cursor: string // 当前分页末尾数据游标
}
data: {
key: string // Key
value: {
name: string // 员工名
age: number // 员工年龄
deleted: boolean // 删除标记
}
}[]
}

使用实体查询对象获取实体数据总数

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee')
.query()
.count()
.then((data) => {
// 获取实体数据总数
console.log(data)
})

返回值类型

backend/src/index.ts
// 获取实体数据总数
type data = number

设置实体查询长度(默认值:10)

实体查询对象支持设置实体查询长度。

支持的输入范围:[1, 1000]

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

entity('employee').query().limit(100).getMany()

设置实体查询排序(默认值:ASC)

实体查询对象支持设置实体查询排序。

只能输入,Sort,排序枚举,其枚举值有:

  • ASC
  • DESC

实体定义中,

  • 没有定义索引时:
    • 按创建数据的时间戳进行排序。
  • 有定义索引时:
    • 按索引的 partition 的属性值、创建数据的时间戳,进行逐级排序。
  • 当按创建数据的时间戳进行排序时,相同的时间戳的数据的排序结果,取决于数据库的表现。

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage
const { Sort } = entity

entity('employee').query().sort(Sort.DESC).getMany()

设置实体查询游标

实体查询对象支持设置实体查询游标。

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

const query = entity('employee').query().limit(10)

// 查询第一页
query.getMany().then((data) => {
// 根据第一页的游标,查询第二页
query
.cursor(data.page_info.end_cursor)
.getMany()
.then((data2) => {
// 第二页的数据
console.log(data2)
})
})

设置实体查询索引

只有在实体定义中,定义了索引的实体,才支持设置实体查询索引。

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage

// 自定义索引
entity('employee').query().index('find_by_name')

// 有分区属性值的自定义索引
// partition: deleted
// 只返回 deleted 为 false 的数据
entity('employee')
.query()
.index('find_by_age_in_deleted_partition', [false])
.getMany()
.then((data) => {
// Mike
// Neo
// Molly
})

设置实体查询条件

只有在实体定义中,定义了索引的实体,才支持设置实体查询条件。

并且,实体查询对象先设置实体查询索引,才支持设置实体查询条件。

只能输入,WhereConditions,实体查询条件方法枚举,其方法枚举值有:

  • beginsWith
  • between
  • equalTo
  • greaterThan
  • lessThan
  • greaterThanEqualTo
  • lessThanEqualTo

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { entity } = storage
const { WhereConditions } = entity

// 自定义索引且设置实体查询条件
// range_attribute: name
// 只返回 name 以 M 开头的数据
entity('employee')
.query()
.index('find_by_name')
.where(WhereConditions.beginsWith('M'))
.getMany()
.then((data) => {
// Mike
// Molly
})

// 有分区属性值的自定义索引且设置实体查询条件
// range_attribute: age
// partition: deleted
// 只返回 deleted 为 true 且 age 大于 0 的数据
entity('employee')
.query()
.index('find_by_age_in_deleted_partition', [true])
.where(WhereConditions.greaterThan(0))
.getMany()
.then((data) => {
// Emma
})

SDK 使用规范

SDK 调用限制

  • 写入超时时间:15秒
  • 查询超时时间:5秒
  • 单次调用最大返回条数:1000条

SDK 数据的写入规范

实体数据的使用规范

SDK 错误处理

实体操作均为异步,以下方法的错误处理,均可参照示例用法:

  • set
  • batchSet
  • delete
  • batchDelete
  • get
  • getOne
  • getMany
  • count

示例用法

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { EntityError } from '@ones-op/sdk/backend'

const { entity } = storage

// 使用 Promise 写法
entity('employee')
.query()
.getOne()
.then((data) => {
console.log(data)
})
.catch((error: EntityError) => {
console.log(error.code)
console.log(error.err_msg)
})

// 使用 Async 写法
async function hello() {
try {
const data = await entity('employee').query().getOne()
console.log(data)
} catch (err: any) {
const error: EntityError = err
console.log(error.code)
console.log(error.err_msg)
}
}

返回值类型

backend/src/index.ts
// 错误对象
type EntityError = {
code: string
err_msg: string
}

SDK 常见错误

错误码描述
EntityNameInvalid实体名称为空/包含非法字符/超出最大长度限制
EntityNotFound实体名称不存在(配置未定义)
EntityDataEmpty实体数据不能为空
EntityDataBatchLimit实体数据过多
EntityDataKeyInvalidkey 为空/包含非法字符/超出最大长度限制
EntityDataKeyDuplicatekey 重复
EntityDataValueAttrInvalid属性名为空/包含非法字符/超出最大长度限制
EntityDataValueAttrNotFound属性名不存在(配置未定义)
EntityDataValueEmpty值不能为空
EntityDataValueInvalid值非法
EntityDataStringValueTooLongstring 类型的属性的值超出最大长度限制
EntityDataTextValueTooLongtext 类型的属性的值超出最大长度限制
EntityDataAttrRequired缺少必填属性
EntityDataValueTypeInvalid属性值的类型与定义的类型不匹配
EntityDataIndexEmpty索引不能为空
EntityDataIndexNameInvalid索引为空/包含非法字符/超出最大长度限制
EntityDataIndexNotFound索引不存在(配置未定义)
EntityDataPartitionValueInvalid自定义索引中的属性值为空/非法
EntityDataPartitionValueTypeInvalid自定义索引中的属性值的类型与定义的类型不匹配
EntityDataPartitionValueTooLong自定义索引中的属性值超出最大长度限制
EntityDataUniqueConstraintFailed数据存在唯一性约束错误
EntityDataWhereConditionValueTypeInvalid实体查询条件的子句的属性值类型不匹配
EntityDataWhereConditionValueTooLong实体查询条件的子句的属性值超出最大长度限制
EntityDataPageCursorInvalid实体查询的游标的值非法
EntityDataSortValueInvalid实体查询的排序的值非法
EntityDataPageLimitNotInRange实体查询的分页长度的值非法
EntityDataAPITimeOut实体操作或者查询超时
MalformedJSONJSON 序列化失败