Moralis 對象

2022-05-12 10:19 更新

Moralis.Object

在 Moralis 上存儲數(shù)據(jù)是圍繞 ?Moralis.Object? 構(gòu)建的。 每個 ?Moralis.Object? 都包含 JSON 兼容數(shù)據(jù)的鍵值對。 此數(shù)據(jù)是無模式的,這意味著您無需提前指定每個 ?Moralis.Object? 上存在哪些鍵。 您只需設(shè)置所需的任何鍵值對,我們的后端就會存儲它們。

例如,假設(shè)您正在構(gòu)建一個角色是?Monster?的 NFT 游戲。 單個 ?Moralis.Object? 可以包含:

?strength?(強度):1024,?ownerName?(所有者名稱):“Aegon”,?canFly?:true

鍵必須是字母數(shù)字字符串。 值可以是字符串、數(shù)字、布爾值,甚至是數(shù)組和字典——任何可以被 JSON 編碼的東西。

每個 ?Moralis.Object? 都是具有類名的特定子類的實例,您可以使用該類名來區(qū)分不同類型的數(shù)據(jù)。 例如,我們可以將該對象稱為 ?LegendaryMonster?。

我們建議您使用 ?NameYourClassesLikeThis ?和 ?nameYourKeysLikeThis?,只是為了讓您的代碼看起來更漂亮。

Moralis.Object.extend()

要創(chuàng)建新的子類,請使用 ?Moralis.Object.extend? 方法。 任何 ?Moralis.Query? 都將為具有相同類名的任何 ?Moralis.Object? 返回新類的實例。 如果您熟悉 ?Backbone.Model?,那么您已經(jīng)知道如何使用 ?Moralis.Object?。 它旨在以相同的方式創(chuàng)建和修改。

// 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.

要創(chuàng)建任何 ?Moralis Object? 類的單個實例,您還可以直接使用 ?Moralis.Object? 構(gòu)造函數(shù)。 ?new Moralis.Object(className)將創(chuàng)建具有該類名的單個 Moralis 對象。

如果您已經(jīng)在代碼庫中使用 ES6。 您可以使用 ?extends ?關(guān)鍵字對 ?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()

假設(shè)您想將上述?Monster?保存到 ?Moralis Cloud?。 接口類似于 ?Backbone.Model?,包括 ?save ?方法:

你可以使用?JS?、?React?、?Unity?來實現(xiàn)

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);
      }
    }

這段代碼運行后,您可能想知道是否真的發(fā)生了什么事。 為了確保數(shù)據(jù)已保存,您可以查看“?Moralis Dashboard?”中的“?Data Browser?”。 您應(yīng)該看到如下內(nèi)容:

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

這里有兩點需要注意:

  1. 在運行此代碼之前,您不必配置或設(shè)置一個名為 ?Monster ?的新類。
  2. 您的 Moralis 應(yīng)用程序在第一次遇到此類時會懶惰地為您創(chuàng)建此類。

還有一些您不需要指定的字段是為了方便而提供的。 ?objectId ?是每個已保存對象的唯一標(biāo)識符。 ?createdAt ?和 ?updatedAt ?表示每個對象在云中創(chuàng)建和最后修改的時間。 這些字段中的每一個都由 Moralis 填寫,因此在完成保存操作之前,它們不存在于 ?Moralis.Object? 上。

如果您愿意,您可以直接在調(diào)用中設(shè)置屬性以進行保存。

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

默認情況下,您創(chuàng)建的類將沒有權(quán)限設(shè)置——這意味著任何人都可以將數(shù)據(jù)寫入類并從類中讀取數(shù)據(jù)。

保存嵌套對象

您可以將 ?Moralis.Object? 添加為另一個 ?Moralis.Object? 中的屬性值。 默認情況下,當(dāng)您在父對象上調(diào)用 ?save()? 時,所有嵌套對象都將在批處理操作中創(chuàng)建和/或保存。 此功能使管理關(guān)系數(shù)據(jù)變得非常容易,因為您不必按照任何特定順序創(chuàng)建對象。

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

在某些情況下,您可能希望阻止此默認鏈保存。 例如,當(dāng)保存一個怪物的配置文件時,它的 ?owner ?屬性指向另一個用戶擁有的帳戶,而您沒有寫入權(quán)限。 在這種情況下,將選項 ?cascadeSave ?設(shè)置為 ?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 ?觸發(fā)器。 如果您想根據(jù)不應(yīng)與 ?Moralis.Object? 一起保存在數(shù)據(jù)庫中的臨時信息來調(diào)整云代碼觸發(fā)器中的某些操作,這將非常有用。 上下文是短暫的,因為它在云代碼觸發(fā)特定 ?Moralis.Object? 后消失,因為它已被執(zhí)行。 例如:

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()

將數(shù)據(jù)保存到云端很有趣,但再次將這些數(shù)據(jù)取出會更有趣。

如果 ?Moralis.Object? 已上傳到服務(wù)器,您可以用 ?objectId ?通過 ?Moralis.Query? 檢索它(可以通過?JS?、?React?實現(xiàn)):

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 對象,甚至可以解構(gòu)。

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 云中當(dāng)前的最新數(shù)據(jù)刷新已有的對象,您可以調(diào)用 ?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()

如果你需要檢查一個對象是否已經(jīng)被獲取,你可以調(diào)用 ?isDataAvailable()? 方法:

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

更新對象

myObject.set()

更新對象很簡單。 只需在其上設(shè)置一些新數(shù)據(jù)并調(diào)用 ?save ?方法。 例如(可以通過?JS?、?React?實現(xiàn)):

// 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 會自動計算出哪些數(shù)據(jù)發(fā)生了變化,因此只有?dirty?字段會被發(fā)送到 Moralis 云。 您無需擔(dān)心壓縮您不打算更新的數(shù)據(jù)。

myObject.increment()

計數(shù)器

上面的示例包含一個常見的用例。 strength field是一個計數(shù)器,我們需要不斷更新monster的最新能量。 使用上述方法是可行的,但它很麻煩,并且如果您有多個客戶端嘗試更新同一個計數(shù)器,可能會導(dǎo)致問題。

為了幫助存儲計數(shù)器類型的數(shù)據(jù),Moralis 提供了自動增加(或減少)任何數(shù)字字段的方法。 因此,相同的更新可以重寫為:

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

您還可以通過將第二個參數(shù)傳遞給 ?increment ?來增加任意數(shù)量。 未指定金額時,默認使用 1。

myObject.addUnique()

數(shù)組

為了幫助存儲數(shù)組數(shù)據(jù),可以使用三種操作來自動更改與給定鍵關(guān)聯(lián)的數(shù)組:

  • ?add ?將給定對象附加到數(shù)組字段的末尾。
  • ?addUnique ?僅當(dāng)它尚未包含在數(shù)組字段中時才添加給定對象。 不能保證插入的位置。
  • ?remove ?從數(shù)組字段中刪除給定對象的所有實例。

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

請注意,目前無法在同一保存中自動從數(shù)組中添加和刪除項目。 您必須在每種不同類型的數(shù)組操作之間調(diào)用 ?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)? 從對象中刪除字段,這會導(dǎo)致意外功能。

關(guān)系數(shù)據(jù)

對象可能與其他對象有關(guān)系。 例如,在博客應(yīng)用程序中,一個 ?Post ?對象可能有許多 ?Comment ?對象。 Moralis 支持各種關(guān)系:

  • 一對一
  • 一對多
  • 多對多。

一對一和一對多

一對一和一對多關(guān)系通過將 ?Moralis.Object? 保存為另一個對象中的值來建模。

例如,博客應(yīng)用程序中的每個評論可能對應(yīng)一個帖子。

要使用單個評論創(chuàng)建新帖子,您可以編寫(可以通過?JS?、?React?來實現(xiàn)):

// 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>;
}

在內(nèi)部,Moralis 將引用對象僅存儲在一個位置,以保持一致性。 您還可以使用它們的 ?objectId ?鏈接對象,如下所示:

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

myComment.set("parent", post);

默認情況下,在獲取對象時,不會獲取相關(guān)的 ?Moralis.Object?。 這些對象的值在被獲取之前無法被檢索,如下所示:

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

多對多

多對多關(guān)系使用 ?Moralis.Relation? 建模。 這類似于將 ?Moralis.Object? 的數(shù)組存儲在一個鍵中,只是您不需要一次獲取關(guān)系中的所有對象。 此外,與 ?Moralis.Object? 方法的數(shù)組相比,這允許 ?Moralis.Relation? 擴展到更多的對象。

例如,用戶可能有許多她可能喜歡的帖子。 在這種情況下,您可以使用關(guān)系存儲用戶喜歡的一組帖子。 要將帖子添加到用戶的“喜歡”列表中,您可以執(zhí)行以下操作:

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

您可以從 ?Moralis.Relation? 中刪除帖子:

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

您可以在調(diào)用 ?save ?之前多次調(diào)用 ?add ?和 ?remove?:

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

您還可以傳入一個 ?Moralis.Object? 數(shù)組來添加和刪除:

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

默認情況下,不會下載此關(guān)系中的對象列表。 您可以使用查詢返回的 ?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".
  },
});

數(shù)據(jù)類型

到目前為止,我們已經(jīng)使用了 ?String?、?Number ?和 ?Moralis.Object? 類型的值。 Moralis 還支持 ?Dates ?和 ?null?。 您可以嵌套 JSON 對象和 JSON 數(shù)組以在單個 ?Moralis.Object? 中存儲更多結(jié)構(gòu)化數(shù)據(jù)。 總體而言,對象中的每個字段都允許以下類型:

  • 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? 上存儲大量二進制數(shù)據(jù),例如圖像或文檔。 我們建議您使用 ?Moralis.File? 來存儲圖像、文檔和其他類型的文件。 您可以通過實例化 ?Moralis.File? 對象并將其設(shè)置在字段上來實現(xiàn)。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號