Moralis 对象

2022-05-12 10:19 更新

Moralis.Object

在 Moralis 上存储数据是围绕 ​Moralis.Object​ 构建的。 每个 ​Moralis.Object​ 都包含 JSON 兼容数据的键值对。 此数据是无模式的,这意味着您无需提前指定每个 ​Moralis.Object​ 上存在哪些键。 您只需设置所需的任何键值对,我们的后端就会存储它们。

例如,假设您正在构建一个角色是​Monster​的 NFT 游戏。 单个 ​Moralis.Object​ 可以包含:

strength​(强度):1024,​ownerName​(所有者名称):“Aegon”,​canFly​:true

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

每个 ​Moralis.Object​ 都是具有类名的特定子类的实例,您可以使用该类名来区分不同类型的数据。 例如,我们可以将该对象称为 ​LegendaryMonster​。

我们建议您使用 ​NameYourClassesLikeThis ​和 ​nameYourKeysLikeThis​,只是为了让您的代码看起来更漂亮。

Moralis.Object.extend()

要创建新的子类,请使用 ​Moralis.Object.extend​ 方法。 任何 ​Moralis.Query​ 都将为具有相同类名的任何 ​Moralis.Object​ 返回新类的实例。 如果您熟悉 ​Backbone.Model​,那么您已经知道如何使用 ​Moralis.Object​。 它旨在以相同的方式创建和修改。

// Simple syntax to create a new subclass of Moralis.Object.
const LegendaryMonster = Moralis.Object.extend("Monster");

// Create a new instance of that class.
const monster = new LegendaryMonster();

// Alternatively, you can use the typical Backbone syntax.
const LegendaryMonster = Moralis.Object.extend({
  className: "Monster",
});

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

// A complex subclass of Moralis.Object
const Monster = Moralis.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) {
      const monster = new Monster();
      monster.set("strength", strength);
      return monster;
    },
  }
);

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

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

如果您已经在代码库中使用 ES6。 您可以使用 ​extends ​关键字对 ​Moralis.Object​ 进行子类化:

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

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

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

但是,使用扩展时,SDK 不会自动识别您的子类。 如果您希望从查询返回的对象使用 ​Moralis.Object​ 的子类,则需要注册子类,类似于我们在其他平台上所做的。

// After specifying the Monster subclass...
Moralis.Object.registerSubclass("Monster", Monster);

同样,您可以将扩展与 ​Moralis.User​ 一起使用。

class CustomUser extends Moralis.User {
  constructor(attributes) {
    super(attributes);
  }

  doSomething() {
    return 5;
  }
}
Moralis.Object.registerSubclass("_User", CustomUser);

除了查询,​logIn ​和 ​signUp ​将返回子类 ​CustomUser​。

const customUser = new CustomUser({ foo: "bar" });
customUser.setUsername("username");
customUser.setPassword("password");
customUser.signUp().then((user) => {
  // user is an instance of CustomUser
  user.doSomething(); // return 5
  user.get("foo"); // return 'bar'
});

CustomUser.logIn​ 和 ​CustomUser.signUp​ 将返回子类 ​CustomUser​。

保存对象

myObject.save()

假设您想将上述​Monster​保存到 ​Moralis Cloud​。 接口类似于 ​Backbone.Model​,包括 ​save ​方法:

你可以使用​JS​、​React​、​Unity​来实现

const Monster = Moralis.Object.extend("Monster");
const monster = new Monster();

monster.set("strength", 1024);
monster.set("ownerName", "Aegon");
monster.set("canFly", true);

monster.save().then(
  (monster) => {
    // Execute any logic that should take place after the object is saved.
    alert("New object created with objectId: " + monster.id);
  },
  (error) => {
    // Execute any logic that should take place if the save fails.
    // error is a Moralis.Error with an error code and message.
    alert("Failed to create new object, with error code: " + error.message);
  }
);
import { useNewMoralisObject } from "react-moralis";

export default function App() {
  const { save } = useNewMoralisObject("Monster");

  const saveObject = async () => {
    const data = {
      strength: 1024,
      ownerName: "Aegon",
      canFly: true,
    };

    save(data, {
      onSuccess: (monster) => {
        // Execute any logic that should take place after the object is saved.
        alert("New object created with objectId: " + monster.id);
      },
      onError: (error) => {
        // Execute any logic that should take place if the save fails.
        // error is a Moralis.Error with an error code and message.
        alert("Failed to create new object, with error code: " + error.message);
      },
    });
  };

  return <button onClick={saveObject}>Call The Code</button>;
}
using Moralis.Platform.Objects;
using MoralisWeb3ApiSdk;
using Newtonsoft.Json;

public class Monster : MoralisObject
{
    public int strength { get; set; }
    public string ownerName { get; set; }
    public bool canFly { get; set; }
}
public async void SaveObjectToDB()
    {
      try {
        Monster monster = MoralisInterface.GetClient().Create<Monster>();
        monster.strength = 1024;
        monster.ownerName = "Aegon";
        monster.canFly = true;
        await character.SaveAsync();
        print("Created new object");
      }
      catch (Exception e){
        print("Failed to create new object, with error code: " + e);
      }
    }

这段代码运行后,您可能想知道是否真的发生了什么事。 为了确保数据已保存,您可以查看“​Moralis Dashboard​”中的“​Data Browser​”。 您应该看到如下内容:

objectId: "xWMyZ4YEGZ", strength: 1024, ownerName: "Aegon", canFly: true,
createdAt:"2011-06-10T18:33:42Z", updatedAt:"2011-06-10T18:33:42Z"

这里有两点需要注意:

  1. 在运行此代码之前,您不必配置或设置一个名为 ​Monster ​的新类。
  2. 您的 Moralis 应用程序在第一次遇到此类时会懒惰地为您创建此类。

还有一些您不需要指定的字段是为了方便而提供的。 ​objectId ​是每个已保存对象的唯一标识符。 ​createdAt ​和 ​updatedAt ​表示每个对象在云中创建和最后修改的时间。 这些字段中的每一个都由 Moralis 填写,因此在完成保存操作之前,它们不存在于 ​Moralis.Object​ 上。

如果您愿意,您可以直接在调用中设置属性以进行保存。

const Monster = Moralis.Object.extend("Monster");
const monster = new Monster();

monster
  .save({
    strength: 1024,
    ownerName: "Aegon",
    canFly: true,
  })
  .then(
    (monster) => {
      // The object was saved successfully.
    },
    (error) => {
      // The save failed.
      // error is a Moralis.Error with an error code and message.
    }
  );

默认情况下,您创建的类将没有权限设置——这意味着任何人都可以将数据写入类并从类中读取数据。

保存嵌套对象

您可以将 ​Moralis.Object​ 添加为另一个 ​Moralis.Object​ 中的属性值。 默认情况下,当您在父对象上调用 ​save()​ 时,所有嵌套对象都将在批处理操作中创建和/或保存。 此功能使管理关系数据变得非常容易,因为您不必按照任何特定顺序创建对象。

const Child = Moralis.Object.extend("Child");
const child = new Child();

const Parent = Moralis.Object.extend("Parent");
const parent = new Parent();

parent.save({ child: child });
// Automatically the object Child is created on the server
// just before saving the Parent

在某些情况下,您可能希望阻止此默认链保存。 例如,当保存一个怪物的配置文件时,它的 ​owner ​属性指向另一个用户拥有的帐户,而您没有写入权限。 在这种情况下,将选项 ​cascadeSave ​设置为 ​false ​可能很有用:

const Monster = Moralis.Object.extend("Monster");
const monster = new Monster();
monster.set("ownerAccount", ownerAccount); // Suppose `ownerAccount` has been created earlier.

monster.save(null, { cascadeSave: false });
// Will save `teamMember` wihout attempting to save or modify `ownerAccount`

云代码上下文

您可以传递一个上下文字典,该字典可在云代码中访问该 ​Moralis.Object​ 的 ​beforeSave ​和 ​afterSave ​触发器。 如果您想根据不应与 ​Moralis.Object​ 一起保存在数据库中的临时信息来调整云代码触发器中的某些操作,这将非常有用。 上下文是短暂的,因为它在云代码触发特定 ​Moralis.Object​ 后消失,因为它已被执行。 例如:

const Monster = Moralis.Object.extend("Monster");
const monster = new Monster();
monster.set("species", "Dragon");

const context = { notifyMonsterGuild: true };
await monster.save(null, { context: context });

然后可以在云代码中访问上下文:

Moralis.Cloud.afterSave("Monster", async (req) => {
  const notifyMonsterGuild = req.context.notifyMonsterGuild;
  if (notifyMonsterGuild) {
    // Notify the guild about new monster.
  }
});

检索对象

myObject.get()

将数据保存到云端很有趣,但再次将这些数据取出会更有趣。

如果 ​Moralis.Object​ 已上传到服务器,您可以用 ​objectId ​通过 ​Moralis.Query​ 检索它(可以通过​JS​、​React​实现):

const Monster = Moralis.Object.extend("Monster");
const query = new Moralis.Query(Monster);

//get monster with id xWMyZ4YEGZ
query.get("xWMyZ4YEGZ").then(
  (monster) => {
    // The object was retrieved successfully.
  },
  (error) => {
    // The object was not retrieved successfully.
    // error is a Moralis.Error with an error code and message.
  }
);
import { useMoralisQuery } from "react-moralis";

export default function App() {
  const { fetch } = useMoralisQuery(
    "Monster",
    (query) => query.equalTo("objectId", "xWMyZ4YEGZ"),
    [],
    { autoFetch: false }
  );

  const objectIdQuery = () => {
    fetch({
      onSuccess: (monster) => {
        // The object was retrieved successfully.
      },
      onError: (error) => {
        // The object was not retrieved successfully.
        // error is a Moralis.Error with an error code and message.
      },
    });
  };

  return <button onClick={objectIdQuery}>Call The Code</button>;
}

要从 ​Moralis.Object​ 中获取值,请使用 ​get ​方法:

const strength = monster.get("strength");
const ownerName = monster.get("ownerName");
const canFly = monster.get("canFly");

或者,可以将 ​Moralis.Object​ 的 ​attributes ​属性视为 JavaScript 对象,甚至可以解构。

const { strength, ownerName, canFly } = result.attributes;

四个特殊的保留值作为属性提供,不能使用“​get​”方法检索,也不能使用“​set​”方法修改:

const updatedAt = monster.updatedAt;
const objectId = monster.id;
const createdAt = monster.createdAt;
const acl = monster.getACL();

myObject.fetch()

如果您需要使用 Moralis 云中当前的最新数据刷新已有的对象,您可以调用 ​fetch ​方法,如下所示:

myObject.fetch().then(
  (myObject) => {
    // The object was refreshed successfully.
  },
  (error) => {
    // The object was not refreshed successfully.
    // error is a Moralis.Error with an error code and message.
  }
);

myObject.isDataAvailable()

如果你需要检查一个对象是否已经被获取,你可以调用 ​isDataAvailable()​ 方法:

if (!myObject.isDataAvailable()) {
  await myObject.fetch();
}

更新对象

myObject.set()

更新对象很简单。 只需在其上设置一些新数据并调用 ​save ​方法。 例如(可以通过​JS​、​React​实现):

// Create the object.
const Monster = Moralis.Object.extend("Monster");
const monster = new Monster();

monster.set("strength", 1024);
monster.set("energy", 1337);
monster.set("owner", "Aegon");
monster.set("canFly", false);
monster.set("skills", ["pwnage", "flying"]);

monster.save().then((monster) => {
  // Now let's update it with some new data. In this case, only canFly and energy
  // will get sent to the cloud. ownerName hasn't changed.
  monster.set("canFly", true);
  monster.set("energy", 1338);
  return monster.save();
});
import { useNewMoralisObject } from "react-moralis";

export default function App() {
  const { save } = useNewMoralisObject("Monster");

  const updateObject = async () => {
    const data = {
      strength: 1024,
      energy: 1337,
      owner: "Aegon",
      canFly: false,
      skills: ["pwnage", "flying"],
    };

    save(data, {
      onSuccess: (monster) => {
        monster.set("canFly", true);
        monster.set("strength", 1338);
        return monster.save();
      },
    });
  };

  return <button onClick={updateObject}>Call The Code</button>;
}

Moralis 会自动计算出哪些数据发生了变化,因此只有​dirty​字段会被发送到 Moralis 云。 您无需担心压缩您不打算更新的数据。

myObject.increment()

计数器

上面的示例包含一个常见的用例。 strength field是一个计数器,我们需要不断更新monster的最新能量。 使用上述方法是可行的,但它很麻烦,并且如果您有多个客户端尝试更新同一个计数器,可能会导致问题。

为了帮助存储计数器类型的数据,Moralis 提供了自动增加(或减少)任何数字字段的方法。 因此,相同的更新可以重写为:

monster.increment("energy");
monster.save();

您还可以通过将第二个参数传递给 ​increment ​来增加任意数量。 未指定金额时,默认使用 1。

myObject.addUnique()

数组

为了帮助存储数组数据,可以使用三种操作来自动更改与给定键关联的数组:

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

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

请注意,目前无法在同一保存中自动从数组中添加和删除项目。 您必须在每种不同类型的数组操作之间调用 ​save ​。

摧毁对象

myObject.destroy()

要从云中删除对象:

myObject.destroy().then(
  (myObject) => {
    // The object was deleted from the Moralis Cloud.
  },
  (error) => {
    // The delete failed.
    // error is a Moralis.Error with an error code and message.
  }
);

myObject.unset()

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

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

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

请注意,不建议使用 ​object.set(null)​ 从对象中删除字段,这会导致意外功能。

关系数据

对象可能与其他对象有关系。 例如,在博客应用程序中,一个 ​Post ​对象可能有许多 ​Comment ​对象。 Moralis 支持各种关系:

  • 一对一
  • 一对多
  • 多对多。

一对一和一对多

一对一和一对多关系通过将 ​Moralis.Object​ 保存为另一个对象中的值来建模。

例如,博客应用程序中的每个评论可能对应一个帖子。

要使用单个评论创建新帖子,您可以编写(可以通过​JS​、​React​来实现):

// Declare the types.
const Post = Moralis.Object.extend("Post");
const Comment = Moralis.Object.extend("Comment");

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

// Create the comment
const 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();
import { useNewMoralisObject } from "react-moralis";

export default function App() {
  const postObject = useNewMoralisObject("Post");
  const commentObject = useNewMoralisObject("Comment");

  const makePost = async () => {
    const postData = {
      title: "I'm Hungry",
      content: "Where should we go for lunch?",
    };

    const commentData = {
      content: "Let's do Sushirrito.",
      parent: await postObject.save(postData),
    };

    commentObject.save(commentData, {
      onSuccess: (comment) => console.log(comment),
      onError: (error) => console.log(error),
    });
  };

  return <button onClick={makePost}>Call The Code</button>;
}

在内部,Moralis 将引用对象仅存储在一个位置,以保持一致性。 您还可以使用它们的 ​objectId ​链接对象,如下所示:

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

myComment.set("parent", post);

默认情况下,在获取对象时,不会获取相关的 ​Moralis.Object​。 这些对象的值在被获取之前无法被检索,如下所示:

const post = fetchedComment.get("parent");
await post.fetch();
const title = post.get("title");

多对多

多对多关系使用 ​Moralis.Relation​ 建模。 这类似于将 ​Moralis.Object​ 的数组存储在一个键中,只是您不需要一次获取关系中的所有对象。 此外,与 ​Moralis.Object​ 方法的数组相比,这允许 ​Moralis.Relation​ 扩展到更多的对象。

例如,用户可能有许多她可能喜欢的帖子。 在这种情况下,您可以使用关系存储用户喜欢的一组帖子。 要将帖子添加到用户的“喜欢”列表中,您可以执行以下操作:

const user = Moralis.User.current();
const relation = user.relation("likes");
relation.add(post);
user.save();

您可以从 ​Moralis.Relation​ 中删除帖子:

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

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

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

您还可以传入一个 ​Moralis.Object​ 数组来添加和删除:

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

默认情况下,不会下载此关系中的对象列表。 您可以使用查询返回的 ​Moralis.Query​ 获取用户喜欢的帖子列表。 代码如下所示:

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

如果您只想要帖子的子集,您可以向查询返回的 ​Moralis.Query​ 添加额外的约束,如下所示:

const 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".
  },
});

数据类型

到目前为止,我们已经使用了 ​String​、​Number ​和 ​Moralis.Object​ 类型的值。 Moralis 还支持 ​Dates ​和 ​null​。 您可以嵌套 JSON 对象和 JSON 数组以在单个 ​Moralis.Object​ 中存储更多结构化数据。 总体而言,对象中的每个字段都允许以下类型:

  • String => ​String
  • Number => ​Number
  • Bool => ​bool
  • Array => ​JSON Array
  • Object => ​JSON Object
  • Date => ​Date
  • File => ​Moralis.File
  • Pointer => other ​Moralis.Object
  • Relation => ​Moralis.Relation
  • Null => ​null

一些例子:

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

const BigObject = Moralis.Object.extend("BigObject");
const 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 &lt;MyClassName&gt; in the Data Browser
bigObject.save();

我们不建议在 ​Moralis.Object​ 上存储大量二进制数据,例如图像或文档。 我们建议您使用 ​Moralis.File​ 来存储图像、文档和其他类型的文件。 您可以通过实例化 ​Moralis.File​ 对象并将其设置在字段上来实现。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号