数据存储开发指南 · JavaScript
数据存储是云服务提供的核心功能之一,可用于存放和查询应用数据。下面的代码展示了如何创建一个对象并将其存入云端:
// 声明 class
const Todo = AV.Object.extend("Todo");
// 构建对象
const todo = new Todo();
// 为属性赋值
todo.set("title", "工程师周会");
todo.set("content", "周二两点,全体成员");
// 将对象保存到云端
todo.save().then(
(todo) => {
// 成功保存之后,执行其他逻辑
console.log(`保存成功。objectId:${todo.id}`);
},
(error) => {
// 异常处理
}
);
我们为各个平台或者语言开发的 SDK 在底层都是通过 HTTPS 协议调用统一的 REST API,提供完整的接口对数据进行各类操作。
SDK 安装与初始化
请阅读 数据存储、即时通讯 JavaScript SDK 配置指南。
对象
AV.Object
AV.Object 是云服务对复杂对象的封装,每个 AV.Object 包含若干与 JSON 格式兼容的属性值对(也称键值对,key-value pairs)。这个数据是无模式化的(schema free),意味着你不需要提前标注每个 AV.Object 上有哪些 key,你只需要随意设置键值对就可以,云端会保存它。
比如说,一个保存着单个 Todo 的 AV.Object 可能包含如下数 据:
title: "给小林发邮件确认会议时间",
isComplete: false,
priority: 2,
tags: ["工作", "销售"]
数据类型
AV.Object 支持的数据类型包括 String、Number、Boolean、Object、Array、Date 等等。你可以通过嵌套的方式在 Object 或 Array 里面存储更加结构化的数据。
AV.Object 还支持两种特殊的数据类型 Pointer 和 File,可以分别用来存储指向其他 AV.Object 的指针以及二进制数据。
AV.Object 同时支持 GeoPoint,可以用来存储地理位置信息。参见 GeoPoint。
以下是一些示例:
// 基本类型
const bool = true;
const number = 2018;
const string = `${number} 流行音乐榜单`;
const date = new Date();
const array = [string, number];
const object = {
number: number,
string: string,
};
// 构建对象
const TestObject = AV.Object.extend("TestObject");
const testObject = new TestObject();
testObject.set("testNumber", number);
testObject.set("testString", string);
testObject.set("testDate", date);
testObject.set("testArray", array);
testObject.set("testObject", object);
testObject.save();
我们不推荐在 AV.Object 里面存储图片、文档等大型二进制数据。每个 AV.Object 的大小不应超过 128 KB。如需存储大型文件,可创建 AV.File 实例并将其关联到 AV.Object 的某个属性上。参见 文件。
注意:时间类型在云端将会以 UTC 时间格式存储,但是客户端在读取之后会转化成本地时间。
开发者中心 > 你的游戏 > 游戏服务 > 云服务 > 数据存储 > 结构化数据 中展示的日期数据也会依据操作系统的时区进行 转换。一个例外是当你通过 REST API 获得数据时,这些数据将以 UTC 呈现。你可以手动对它们进行转换。
若想了解云服务是如何保护应用数据的,请阅读数据和安全。
构建对象
下面的代码构建了一个 class 为 Todo 的 AV.Object:
// 为 AV.Object 创建子类
const Todo = AV.Object.extend("Todo");
// 为该类创建一个新实例
const todo = new Todo();
// 你还可以直接使用 AV.Object 的构造器
const todo = new AV.Object("Todo");
在构建对象时,为了使云端知道对象属于哪个 class,需要将 class 的名字作为参数传入。你可以将云服务里面的 class 比作关系型数据库里面的表。一个 class 的名字必须以字母开头,且只能包含数字、字母和下划线。
如果你使用的是 ES6,还可以通过 extends 关键字来创建 AV.Object 的子类,然而 SDK 无法自动识别你创建的子类。你需要通过这种方式手动注册一下:
class Todo extends AV.Object {
// 自定义属性和方法
}
// 注册子类
AV.Object.register(Todo);
这样你就能在 AV.Object 的子类中添加额外的方法和属性了。
保存对象
下面的代码将一个 class 为 Todo 的对象存入云端:
// 声明 class
const Todo = AV.Object.extend("Todo");
// 构建对象
const todo = new Todo();
// 为属性赋值
todo.set("title", "马拉松报名");
todo.set("priority", 2);
// 将对象保存到云端
todo.save().then(
(todo) => {
// 成功保存之后,执行其他逻辑
console.log(`保存成功。objectId:${todo.id}`);
},
(error) => {
// 异常处理
}
);
为了确认对象已经保存成功,我们可以到 开发者中心 > 你的游戏 > 游戏服务 > 云服务 > 数据存储 > 结构化数据 > Todo 里面看一下,应该会有一行新的数据 产生。点一下这个数据的 objectId,应该能看到类似这样的内容:
{
"title": "马拉松报名",
"priority": 2,
"ACL": {
"*": {
"read": true,
"write": true
}
},
"objectId": "582570f38ac247004f39c24b",
"createdAt": "2017-11-11T07:19:15.549Z",
"updatedAt": "2017-11-11T07:19:15.549Z"
}
注意,无需在 开发者中心 > 你的游戏 > 游戏服务 > 云服务 > 数据存储 > 结构化数据 里面创建新的 Todo class 即可运行前面的代码。如果 class 不存在,它将自动创建。
以下是一些对象的内置属性,会在对象保存时自动创建,无需手动指定:
| 内置属性 | 类型 | 描述 |
|---|---|---|
objectId | String | 该对象唯一的 ID 标识。 |
ACL | AV.ACL | 该对象的权限控制,实际上是一个 JSON 对象,控制台做了展现优化。 |
createdAt | Date | 该对象被创建的时间。 |
updatedAt | Date | 该对象最后一次被修改的时间。 |
这些属性的值会在对象被存入云端时自动填入,代码中尚未保存的 AV.Object 不存在这些属性。
属性名(keys)只能包含字母、数字和下划线。自定义属性不得以双下划线(__)开头或与任何系统保留字段和内置属性(ACL、className、createdAt、objectId 和 updatedAt)重名,无论大小写。
属性值(values)可以是字符串、数字、布尔值、数组或字典(任何能以 JSON 编码的数据)。参见 数据类型。
我们推荐使用驼峰式命名法(CamelCase)为类和属性来取名。类,采用大驼峰法,如 CustomData。属性,采用小驼峰法,如 imageUrl。
获取对象
对于已经保存到云端的 AV.Object,可以通过它的 objectId 将其取回:
const query = new AV.Query("Todo");
query.get("582570f38ac247004f39c24b").then((todo) => {
// todo 就是 objectId 为 582570f38ac247004f39c24b 的 Todo 实例
const title = todo.get("title");
const priority = todo.get("priority");
// 获取内置属性
const objectId = todo.id;
const updatedAt = todo.updatedAt;
const createdAt = todo.createdAt;
});
如果你试图获取一个不存在的属性,SDK 不会报错,而是会返回 undefined。
如果需要一次性获取返回对象的所有属性(比如进行数据绑定)而非显式地调用 get,可以利用 AV.Object 实例的 toJSON 方法:
const query = new AV.Query("Todo");
query.get("582570f38ac247004f39c24b").then((todo) => {
console.log(todo.toJSON());
// {
// createdAt: "2017-03-08T11:25:07.804Z",
// objectId: "582570f38ac247004f39c24b",
// priority: 2,
// title: "工程师周会",
// updatedAt: "2017-03-08T11:25:07.804Z"
// }
});