对象

Parse.Object

Parse的对象存储是建立在Parse.Object上,每一个Parse.Object包含了JSON格式的键值对,它的数据是无模式的,这意味着你无需提前为每一个Parse.Object 指定存在的键,你只需要设置任何你想要的键值对就行了,后端会自动创建并存储它。

举例说明,假设你正在记录游戏玩家的分数,一个Parse.Object 可以包含:

  1. score: 1337, playerName: "Sean Plott", cheatMode: false

键名必须是字母和数字组成的string类型的,键值可以是string、boolean、array和任何可以被JSON编码的类型。

每一个Parse.Object 都是一个使用表名构造的表记录对象。你可以通过不同的实例来区分不同的数据。为了让你的代码更加诗意,我们推荐你使用驼峰命名,就像gameScore或者GameScore。


要创建一个新的子类,使用Parse.Object.extend 方法即可。如果你熟悉Backbone.Model,那么你已经知道如何去使用Parse.Object了,它们创建和修改的设计是一样的。

  1. // 创建一个新的Parse.Object子类
  2. var GameScore = Parse.Object.extend("GameScore");
  3. // 创建一个新的子类实例
  4. var gameScore = new GameScore();
  5. // 你也可以使用backbone的语法直接创建.
  6. var Achievement = Parse.Object.extend({
  7. className: "Achievement"
  8. });

你可以添加额外的方法和属性到你的Parse.Object子类:

  1. // 一个复杂的Parse.Object子类
  2. var Monster = Parse.Object.extend("Monster", {
  3. // 实例方法
  4. hasSuperHumanStrength: function () {
  5. return this.get("strength") > 18;
  6. },
  7. // 实例属性
  8. initialize: function (attrs, options) {
  9. this.sound = "Rawr"
  10. }
  11. }, {
  12. // 类方法
  13. spawn: function(strength) {
  14. var monster = new Monster();
  15. monster.set("strength", strength);
  16. return monster;
  17. }
  18. });
  19. var monster = Monster.spawn(200);
  20. alert(monster.get('strength')); // Displays 200.
  21. alert(monster.sound); // Displays Rawr.

如果想为任意一个对象创建一个实例,你也可以使用Parse.Object直接构造。new Parse.Object(className)将会创建一个指定类名的实例。

如果你的项目已经使用了ES6,恭喜!从1.6.0版本开始,JavaScript SDK 已经和ES6类兼容,你可以使用extends关键词继承Parse.Object

  1. class Monster extends Parse.Object {
  2. constructor() {
  3. // Pass the ClassName to the Parse.Object constructor
  4. super('Monster');
  5. // All other initialization
  6. this.sound = 'Rawr';
  7. }
  8. hasSuperHumanStrength() {
  9. return this.get('strength') > 18;
  10. }
  11. static spawn(strength) {
  12. var monster = new Monster();
  13. monster.set('strength', strength);
  14. return monster;
  15. }
  16. }

但是,当你使用extends时,SDK将不会自动识别你的子类。如果你想要查询返回的对象使用你的Parse.Object子类,你将需要注册这个子类,就像我们在其他平台做的一样:

  1. // 指定Monster子类以后
  2. Parse.Object.registerSubclass('Monster', Monster);

保存对象

假设你想保存之前描述的对象GameScore到Parse服务器,这个接口和BackBone.Model类似,即save方法:

  1. var GameScore = Parse.Object.extend("GameScore");
  2. var gameScore = new GameScore();
  3. gameScore.set("score", 1337);
  4. gameScore.set("playerName", "Sean Plott");
  5. gameScore.set("cheatMode", false);
  6. gameScore.save(null, {
  7. success: function(gameScore) {
  8. // 保存成功
  9. alert('New object created with objectId: ' + gameScore.id);
  10. },
  11. error: function(gameScore, error) {
  12. // 包含了错误码和错误信息
  13. alert('Failed to create new object, with error code: ' + error.message);
  14. }
  15. });

在上面代码运行后,你可能会想确认是否真的保存成功了,你可以在Parse的数据浏览器中查看,你将会看到类似下面的数据:

  1. objectId: "xWMyZ4YEGZ", score: 1337, playerName: "Sean Plott", cheatMode: false,
  2. createdAt:"2011-06-10T18:33:42Z", updatedAt:"2011-06-10T18:33:42Z"

取得对象

比保存数据到云端更有趣的是,从云端再次取回数据。如果你已经有了objectId,你可以通过Parse.Query来获得完整的Parse.Object

  1. var GameScore = Parse.Object.extend("GameScore");
  2. var query = new Parse.Query(GameScore);
  3. query.get("xWMyZ4YEGZ", {
  4. success: function(gameScore) {
  5. // The object was retrieved successfully.
  6. },
  7. error: function(object, error) {
  8. // The object was not retrieved successfully.
  9. // error is a Parse.Error with an error code and message.
  10. }
  11. });

通过get方法,即可从Parse.Object中获得值:

  1. var score = gameScore.get("score");
  2. var playerName = gameScore.get("playerName");
  3. var cheatMode = gameScore.get("cheatMode");

有三个值的键名是预留的属性,无法通过get方法获取,也不能通过set方法修改:

  1. var objectId = gameScore.id;
  2. var updatedAt = gameScore.updatedAt;
  3. var createdAt = gameScore.createdAt;

如果你需要更新一个已有的对象,你可以调用fetch方法,获取云端的最新数据:

  1. myObject.fetch({
  2. success: function(myObject) {
  3. // The object was refreshed successfully.
  4. },
  5. error: function(myObject, error) {
  6. // The object was not refreshed successfully.
  7. // error is a Parse.Error with an error code and message.
  8. }
  9. });

更新对象

更新对象超级简单,只需要设置一些新数据,然后调用save方法就可以了:

  1. // Create the object.
  2. var GameScore = Parse.Object.extend("GameScore");
  3. var gameScore = new GameScore();
  4. gameScore.set("score", 1337);
  5. gameScore.set("playerName", "Sean Plott");
  6. gameScore.set("cheatMode", false);
  7. gameScore.set("skills", ["pwnage", "flying"]);
  8. gameScore.save(null, {
  9. success: function(gameScore) {
  10. // Now let's update it with some new data. In this case, only cheatMode and score
  11. // will get sent to the cloud. playerName hasn't changed.
  12. gameScore.set("cheatMode", true);
  13. gameScore.set("score", 1338);
  14. gameScore.save();
  15. }
  16. });

Parse会自动判断哪些数据是修改过的,所有只有”脏”字段会被发送到云端。

计数器

上述的例子中包含了常用的使用情况,但score字段是一个计数器,我们需要不断的更新玩家最后的分数,上述的方法虽然也可用,但是过于麻烦,而且如果你有多个客户端同时更新,可能回导致一些问题。

为了存储计数器类型的数据,Parse提供了原子级增减的方法,incrementdecrement 。所以,计数器的更新我们可以这样写:

  1. gameScore.increment("score");
  2. gameScore.save();

你可以给incrementdecrement传入第二个参数,作为要增减的数值,如果没有传入,默认是1。

数组

为了存储数组型数据,我们提供了三个方法,可以原子级操作给定键值的数组:

  • add增加一个元素到对象的数组字段的尾部。
  • addUnique如果指定数组字段中不包含这个元素,才插入这个元素到数组中。不保证插入的位置。
  • remove从给定对象的数组字段中移除所有元素。

举例说明,比如我们要添加一些元素到“skills”字段中,可以这样:

  1. gameScore.addUnique("skills", "flying");
  2. gameScore.addUnique("skills", "kungfu");
  3. gameScore.save();

注意,目前不支持在同一次save中,原子级addremove数组字段中的元素,你必须在每次不同的数组操作后调用save


删除对象

从云端删除一个对象:

  1. myObject.destroy({
  2. success: function(myObject) {
  3. // The object was deleted from the Parse Cloud.
  4. },
  5. error: function(myObject, error) {
  6. // The delete failed.
  7. // error is a Parse.Error with an error code and message.
  8. }
  9. });

你可以用unset方法从对象中删除一个字段:

  1. // 删除playerName字段
  2. myObject.unset("playerName");
  3. // Saves the field deletion to the Parse Cloud.
  4. // If the object's field is an array, call save() after every unset() operation.
  5. myObject.save();

请注意,不推荐使用object.set(null)的方式从对象中删除字段,这可能会造成意外的问题。


关系型数据

一个对象可能和其他对象存在关联,比如,一个博客应用中,一篇文章(Post)的对象,可能关联着许多评论(Comment)对象。Parse支持所有的关系类型,包括一对一,一对多,多对多。

一对一和一对多

一对一和一对多关系,是通过将Parse.Object的值设为其他对象来模型化的,比如,每个Comment对象,都对应了一个Post对象。

要创建一篇新文章和一条评论,你可以这样写:

  1. // Declare the types.
  2. var Post = Parse.Object.extend("Post");
  3. var Comment = Parse.Object.extend("Comment");
  4. // 创建Post
  5. var myPost = new Post();
  6. myPost.set("title", "I'm Hungry");
  7. myPost.set("content", "Where should we go for lunch?");
  8. // 创建Comment
  9. var myComment = new Comment();
  10. myComment.set("content", "Let's do Sushirrito.");
  11. // 设置关系
  12. myComment.set("parent", myPost);
  13. // 保存
  14. myComment.save();

在内部,Parse框架只会把引用对象存储在一处,以保证一致性。你也可以通过objectId来指向关联对象:

  1. var post = new Post();
  2. post.id = "1zEcyElZ80";
  3. myComment.set("parent", post);

默认情况下,在拉取一个对象时,是不会将关联的对象一起拉取的,关联的对象需要再次拉取:

  1. var post = fetchedComment.get("parent");
  2. post.fetch({
  3. success: function(post) {
  4. var title = post.get("title");
  5. }
  6. });

多对多关系

多对多关系是通过Parse.Relation模型化的。这和存储一个对象到数组字段中类似,不同之处在于,你不需要一次拉取这个关系中的所有对象。另外这允许你拓展多于数组字段的对象。

假如,一个User可能有许多她喜欢的的Posts,那么你可以把User喜欢的Posts作为relation,要添加一篇Post到她喜欢的列表中,你可以这么做:

  1. var user = Parse.User.current();
  2. var relation = user.relation("likes");
  3. relation.add(post);
  4. user.save();

你可以这样从Parse.Relation中删除一篇文章:

  1. relation.remove(post);
  2. user.save();

你可以多次使用addremove再调用save

  1. relation.remove(post1);
  2. relation.remove(post2);
  3. user.save();

你也可以通过传入一个Parse.Object数组来add或者remove

  1. relation.add([post1, post2, post3]);
  2. user.save();

默认情况下,关联的对象列表是没有拉取到本地,你可以使用query返回的Parse.Query得到用户喜欢的文字列表:

  1. relation.query().find({
  2. success: function(list) {
  3. // list contains the posts that the current user likes.
  4. }
  5. });

如果你只想要Posts的部分子集,你可以添加额外的条件到query

  1. var query = relation.query();
  2. query.equalTo("title", "I'm Hungry");
  3. query.find({
  4. success:function(list) {
  5. // list contains post liked by the current user which have the title "I'm Hungry".
  6. }
  7. });

更多关于Parse.Query的详情,请查看指南的查询(Queries)章节。Parse.Relation的查询和Parse.Object的查询类似,所以Parse.Object的任何查询,都可以用在Parse.Relation上。


数据类型

目前为止,我们使用的键值的类型有String、Number、和Parse.Object。Parse也支持Date和null。你还可以存储JSON Object 和JSON Array到你的Parse.Object。下面列出的,是对象的字段支持的所有类型:

  • String =>String
  • Number =>Number
  • Bool =>bool
  • Array =>JSON Array
  • Object =>JSON Object
  • Date =>Date
  • File =>Parse.File
  • Pointer => otherParse.Object
  • Relation =>Parse.Relation
  • Null =>null

一些例子:

  1. var number = 42;
  2. var bool = false;
  3. var string = "the number is " + number;
  4. var date = new Date();
  5. var array = [string, number];
  6. var object = { number: number, string: string };
  7. var pointer = MyClassName.createWithoutData(objectId);
  8. var BigObject = Parse.Object.extend("BigObject");
  9. var bigObject = new BigObject();
  10. bigObject.set("myNumber", number);
  11. bigObject.set("myBool", bool);
  12. bigObject.set("myString", string);
  13. bigObject.set("myDate", date);
  14. bigObject.set("myArray", array);
  15. bigObject.set("myObject", object);
  16. bigObject.set("anyKey", null); // this value can only be saved to an existing key
  17. bigObject.set("myPointerKey", pointer); // shows up as Pointer <MyClassName> in the Data Browser
  18. bigObject.save();

我们不推荐在对象中存储大件的二进制文件,比如图片和文档。对象应该在128字节以内。

我们推荐你使用Parse.File来存储文件、图片,和其他文件 。你可以初始化一个Parse.File对象设置你的文件。具体可以看文件(Files)章节。

关于Parse处理数据的更多信息,请查看文档的数据(Data)章节。

#