02.对象Objects

对象

1.Parse.Object

在Parse上使用Parse.Object存储数据。每个Parse.Object都包含与JSON兼容的键值对。这些数据是无模式的,这意味着您不需要提前指定每个Parse.Object上存在什么key。您只需设置任何所需的键值对,后端就会存储它。

例如,假设您正在跟踪游戏的高分。一个Parse.Object可以包含:

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

键名必须是字母数字字符串。值可以是字符串、数字、布尔值,甚至数组和字典——可以进行JSON编码的任何值。

每个Parse.Object都是具有类名的特定子类的实例,您可以使用它来区分不同类型的数据。例如,我们可以叫高分对象为GameScore。为了保持你的代码看起来漂亮,我们建议您使用如下命名方式:NameYourClassesLikeThis和nameYourKeysLikeThis。

要创建一个新的子类,请使用Parse.Object.extend方法。任何Parse.Query操作都将返回与Parse.Object具有相同类名的新类实例。如果你熟悉Backbone.Model,那么你已经知道如何使用Parse.Object了。它被设计为以相同的方式创建和修改对象。

// Simple syntax to create a new subclass of Parse.Object.
var GameScore = Parse.Object.extend("GameScore");

// Create a new instance of that class.
var gameScore = new GameScore();

// Alternatively, you can use the typical Backbone syntax.
var Achievement = Parse.Object.extend({
  className: "Achievement"
});

您可以向Parse.Object的子类添加其他方法和属性。

// A complex subclass of Parse.Object
var Monster = Parse.Object.extend("Monster", {
  // Instance methods
  hasSuperHumanStrength: function () {
    return this.get("strength") > 18;
  },
  // Instance properties go in an initialize method
  initialize: function (attrs, options) {
    this.sound = "Rawr"
  }
}, {
  // Class methods
  spawn: function(strength) {
    var monster = new Monster();
    monster.set("strength", strength);
    return monster;
  }
});

var monster = Monster.spawn(200);
alert(monster.get('strength'));  // Displays 200.
alert(monster.sound); // Displays Rawr.

要创建任何Parse Object类的单个实例,还可以直接使用Parse.Object构造函数。new Parse.Object(className)将使用该类名创建一个单独的Parse对象。

如果您已经在代码库中使用ES6,好消息!从1.6.0版起,JavaScript SDK与ES6类兼容。您可以使用extends关键字对Parse.Object进行子类化:

class Monster extends Parse.Object {
  constructor() {
    // Pass the ClassName to the Parse.Object constructor
    super('Monster');
    // All other initialization
    this.sound = 'Rawr';
  }

  hasSuperHumanStrength() {
    return this.get('strength') > 18;
  }

  static spawn(strength) {
    var monster = new Monster();
    monster.set('strength', strength);
    return monster;
  }
}

但是,在使用extends时,SDK不会自动识别您的子类。如果您希望从查询返回的对象使用您的Parse.Object子类,则需要注册该子类,类似于我们在其他平台上执行的操作。

// After specifying the Monster subclass...
Parse.Object.registerSubclass('Monster', Monster);

2.保存对象

假设您想把上述的GameScore保存到Parse Cloud中。接口类似于一个包含save方法的Backbone.Model:

var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();

gameScore.set("score", 1337);
gameScore.set("playerName", "Sean Plott");
gameScore.set("cheatMode", false);

gameScore.save(null, {
  success: function(gameScore) {
    // Execute any logic that should take place after the object is saved.
    alert('New object created with objectId: ' + gameScore.id);
  },
  error: function(gameScore, error) {
    // Execute any logic that should take place if the save fails.
    // error is a Parse.Error with an error code and message.
    alert('Failed to create new object, with error code: ' + error.message);
  }
});

在这段代码运行之后,你可能想知道是否确实产生了什么效果。为了确保数据已被保存,您可以在Parse中查看应用程序的数据浏览器。可以看到这样的内容:

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

这里需要注意两点。在运行此代码之前,您不必配置或设置一个新的GameScore类。您的Parse应用程序在首次碰到时,就会直接创建此类。

还有一些为了使用方便而建立的字段,是不需要指定其值的:

  • objectId是每个已保存对象的唯一标识符。
  • createdAt和updatedAt表示每个对象在云端创建和上次修改的时间。

每个这些字段都由Parse填充,所以直到保存操作完成前,他们在Parse.Object中并不存在。

如果您愿意,您可以在调用save中直接设置这些属性。

var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();

gameScore.save({
  score: 1337,
  playerName: "Sean Plott",
  cheatMode: false
}, {
  success: function(gameScore) {
    // The object was saved successfully.
  },
  error: function(gameScore, error) {
    // The save failed.
    // error is a Parse.Error with an error code and message.
  }
});

3.检索对象

将数据保存到云端很有趣,但再次获取这些数据更为有趣。如果你有objectId,你可以使用Parse.Query检索整个Parse.Object:

var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
query.get("xWMyZ4YEGZ", {
  success: function(gameScore) {
    // The object was retrieved successfully.
  },
  error: function(object, error) {
    // The object was not retrieved successfully.
    // error is a Parse.Error with an error code and message.
  }
});

要获取值Parse.Object,可使用get方法。

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

这三个特殊保留值作为属性,是不能使用'get'方法检索,也不能使用'set'方法进行修改:

var objectId = gameScore.id;
var updatedAt = gameScore.updatedAt;
var createdAt = gameScore.createdAt;

如果您需要刷新已有的对象在Parse Cloud中的最新数据,则可以调用fetch方法:

myObject.fetch({
  success: function(myObject) {
    // The object was refreshed successfully.
  },
  error: function(myObject, error) {
    // The object was not refreshed successfully.
    // error is a Parse.Error with an error code and message.
  }
});

4.更新对象

更新对象很简单。只需设置一些新的数据,并调用save方法。例如:

// Create the object.
var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();

gameScore.set("score", 1337);
gameScore.set("playerName", "Sean Plott");
gameScore.set("cheatMode", false);
gameScore.set("skills", ["pwnage", "flying"]);

gameScore.save(null, {
  success: function(gameScore) {
    // Now let's update it with some new data. In this case, only cheatMode and score
    // will get sent to the cloud. playerName hasn't changed.
    gameScore.set("cheatMode", true);
    gameScore.set("score", 1338);
    gameScore.save();
  }
});

Parse会自动计算出哪些数据已更改,因此只有“脏”字段才会发送到Parse Cloud。您不用费心去压缩不打算更新的数据。

计数器

上面的例子是一个常见的用例。“score”字段是一个需要不断更新玩家最新分数的计数器。使用上面的方法是有效的,但是它很麻烦,如果有多个客户端尝试更新同一个计数器,可能会导致问题。

为了有助于存储计数器类型的数据,Parse提供了原子增加(或减少)任何数字字段的方法。所以,同样的更新可以重写为:

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

您还可以向increment方法传递第二个参数来指定增加任意数量。当没有指定数量时,默认情况下增加1。

数组

为了存储数组,以下三个方法可以用于原子更改与给定键相关联的数组:

  • add:将给定的对象附加到数组字段的末尾。
  • addUnique:只有当它不包含在数组字段中时才添加给定的对象。插入位置不能保证。
  • remove:从数组字段中删除给定对象的所有实例。

例如,我们可以将项目添加到类似“skills”字段的集合中,如下所示:

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

请注意,目前不能在同一次保存中从数组中原子添加和删除项目。您必须在不同类型的数组操作之间调用save。

5.销毁对象

要从云中删除对象:

myObject.destroy({
  success: function(myObject) {
    // The object was deleted from the Parse Cloud.
  },
  error: function(myObject, error) {
    // The delete failed.
    // error is a Parse.Error with an error code and message.
  }
});

您可以使用unset方法从对象中删除单个字段:

// After this, the playerName field will be empty
myObject.unset("playerName");

// Saves the field deletion to the Parse Cloud.
// If the object's field is an array, call save() after every unset() operation.
myObject.save();

请注意,不推荐使用object.set(null)从对象中删除字段,因为它将导致意想不到的结果。

6.关系数据

对象可能与其他对象有关系。例如,在博客应用程序中,一个Post对象可能有很多Comment对象。Parse支持各种关系,包括一对一,一对多和多对多。

一对一和一对多关系

一对一和一对多关系都通过将一个Parse.Object作为值保存到另一个对象中来建模。例如,博客应用中的每个Comment都有一个Post与之对应。

要创建包含单个Comment的新Post对象,可以这样写:

// Declare the types.
var Post = Parse.Object.extend("Post");
var Comment = Parse.Object.extend("Comment");

// Create the post
var myPost = new Post();
myPost.set("title", "I'm Hungry");
myPost.set("content", "Where should we go for lunch?");

// Create the comment
var myComment = new Comment();
myComment.set("content", "Let's do Sushirrito.");

// Add the post as a value in the comment
myComment.set("parent", myPost);

// This will save both myPost and myComment
myComment.save();

在内部,Parse框架将会把引用对象存储在同一个位置,以保持一致性。你也可以使用objectId来链接对象,如:

var post = new Post();
post.id = "1zEcyElZ80";

myComment.set("parent", post);

默认情况下,当获取对象时,Parse.Object不会获取相关的对象。这些对象的值无法检索到,直到它们被这样读取:

var post = fetchedComment.get("parent");
post.fetch({
  success: function(post) {
    var title = post.get("title");
  }
});

多对多关系

使用Parse.Relation为多对多关系建模。除了您不需要一次获取关系中的所有对象,这个过程类似于将Parse.Object数组存储在一个键中。此外,Parse.Relation允许扩展比Parse.Object数组方法更多的对象。例如,一个User可能会喜欢许多Posts。在这种情况下,你可以使用relation存储一个User喜欢的一组Posts。为了添加一个Post到User的“likes”列表中,你可以这样做:

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

您可以从Parse.Relation的删除帖子:

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

您可以在调用save之前,调用add和remove多次:

relation.remove(post1);
relation.remove(post2);
user.save();

您也可以传入一个Parse.Object数组来add和remove:

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

默认情况下,此关系中的对象列表未下载。可以通过query返回的Parse.Query获取用户喜欢的帖子列表。代码如下:

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

如果你只想要帖子的一个子集,可以在query返回的Parse.Query上添加额外的约束:

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

有关Parse.Query的详细信息,请参阅本指南的查询(queries)部分。一个Parse.Relation的行为类似于用于查询目的的Parse.Object数组,所以在Parse.Object数组上能执行的查询都可以在Parse.Relation上执行。

7.数据类型

到目前为止,我们已经使用了值类型String,Number和Parse.Object。Parse也支持Dates和null。您可以嵌套JSON Objects和JSON Arrays以在单个Parse.Object中存储更多的结构化数据。总的来说,对象中的每个字段允许使用以下类型:

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

一些例子:

var number = 42;
var bool = false;
var string = "the number is " + number;
var date = new Date();
var array = [string, number];
var object = { number: number, string: string };
var pointer = MyClassName.createWithoutData(objectId);

var BigObject = Parse.Object.extend("BigObject");
var bigObject = new BigObject();
bigObject.set("myNumber", number);
bigObject.set("myBool", bool);
bigObject.set("myString", string);
bigObject.set("myDate", date);
bigObject.set("myArray", array);
bigObject.set("myObject", object);
bigObject.set("anyKey", null); // this value can only be saved to an existing key
bigObject.set("myPointerKey", pointer); // shows up as Pointer  in the Data Browser
bigObject.save();

我们不建议存储大量二进制数据,如图像或文档Parse.Object。Parse.Objects不应超过128KB。我们建议您使用Parse.Files存储图像、文档和其他类型的文件。您可以通过实例化一个Parse.File对象并将其设置在字段上来实现。有关详细信息,请参阅文件部分。

有关Parse如何处理数据的更多信息,请查看我们文档的数据。

你可能感兴趣的:(02.对象Objects)