Moralis 查詢

2022-05-11 14:01 更新

我們已經看到了帶有 ?get ?的 ?Moralis.Query? 如何從 Moralis 中檢索單個 ?Moralis.Object?。 還有許多其他方法可以使用 ?Moralis.Query? 檢索數(shù)據。 您可以一次檢索多個對象,對要檢索的對象設置條件等等。

基本查詢

在許多情況下,?get ?功能不足以指定要檢索的對象。 ?Moralis.Query? 提供了不同的方法來檢索對象列表,而不僅僅是單個對象。

一般模式是創(chuàng)建一個 ?Moralis.Query?,在其上設置條件,然后使用 ?find ?檢索匹配的 ?Moralis.Objects? 數(shù)組。 例如,要檢索具有特定 ?ownerName? 的monster,請使用 ?equalTo ?方法來約束鍵的值。

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

const Monster = Moralis.Object.extend("Monster");
const query = new Moralis.Query(Monster);
query.equalTo("ownerName", "Aegon");
const results = await query.find();
alert("Successfully retrieved " + results.length + " monsters.");
// Do something with the returned Moralis.Object values
for (let i = 0; i < results.length; i++) {
  const object = results[i];
  alert(object.id + " - " + object.get("ownerName"));
}
import { useMoralisQuery } from "react-moralis";

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

  const basicQuery = async () => {
    const results = await fetch();
    alert("Successfully retrieved " + results.length + " monsters.");
    // Do something with the returned Moralis.Object values
    for (let i = 0; i < results.length; i++) {
      const object = results[i];
      alert(object.id + " - " + object.get("ownerName"));
    }
  };

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

 public async void RetrieveObjectFromDB()
    {
        MoralisQuery<Monster> monster = MoralisInterface.GetClient().Query<Monster>().WhereEqualTo("ownerName", "Aegon");
        IEnumerable<Monster> result = await monster.FindAsync();
        foreach(Monster mon in result)
        {
            print("My strength is " + mon.strength + " and can i fly ? " + mon.canFly);
            // output : My strength is 1024 and can i fly ? true
        }
    }

使用主密鑰

在某些情況下,查詢需要主密鑰,

例如,如果您想獲取所有用戶的列表,您只能使用主密鑰在云功能中執(zhí)行此操作 - 因為由于 ACL,用戶無法讀取其他用戶的信息。

query.find({ useMasterKey: true });

查詢約束

有幾種方法可以對 ?Moralis.Query? 找到的對象施加約束。 您可以使用 ?notEqualTo ?過濾掉具有特定鍵值對的對象:

query.notEqualTo("ownerName", "Daenerys");

您可以提供多個約束,并且對象只有在匹配所有約束時才會出現(xiàn)在結果中。 換句話說,它就像約束的 ?AND?。

query.notEqualTo("ownerName", "Daenerys");
query.greaterThan("ownerAge", 18);

您可以通過設置限制來限制結果的數(shù)量。 默認情況下,結果限制為 100。在舊的 Moralis 托管后端中,最大限制為 1,000,但 Moralis Dapps 現(xiàn)在刪除了該限制:

query.limit(10); // limit to at most 10 results

如果您只想要一個結果,更方便的替代方法可能是使用?first?而不是使用 ?find?(可以通過?JS?、?React?實現(xiàn))。

const Monster = Moralis.Object.extend("Monster");
const query = new Moralis.Query(Monster);
query.equalTo("ownerEmail", "daenerys@housetargaryen.com");
const object = await query.first();
import { useMoralisQuery } from "react-moralis";

export default function App() {
  const { fetch } = useMoralisQuery(
    "Monster",
    (query) =>
      query.equalTo("ownerEmail", "daenerys@housetargaryen.com").first(),
    [],
    { autoFetch: false }
  );

  const singleQuery = () =>
    fetch({
      onSuccess: (result) => console.log(result),
    });

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

您可以通過設置 skip 來跳過第一個結果。 在舊的 Moralis 托管后端中,最大skip值為 10,000,但 Moralis Dapps 現(xiàn)在取消了該限制。 這對于分頁很有用:

query.skip(10); // skip the first 10 results

獲取滿足您查詢的表中的總行數(shù),例如 分頁目的 - 您可以使用 ?withCount?。

注意:啟用此標志將更改響應的結構,請參見下面的示例。

示例 - 假設您在名為 Monster 的表中有 200 行(可以通過?JS?、?React?實現(xiàn)):

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

query.limit(25);

const results = await query.find(); // [ Monster, Monster, ...]

// to include count:
query.withCount();
const response = await query.find(); // { results: [ Monster, ... ], count: 200 }
const limitQuery = useMoralisQuery("Monster", (query) => query.limit(25), [], {
  autoFetch: false,
});

const getLimitedQuery = () =>
  limitQuery.fetch({
    onSuccess: (result) => console.log(result), // [ Monster, Monster, ...]
  });

const queryCount = useMoralisQuery(
  "Monster",
  (query) => query.withCount(),
  [],
  {
    autoFetch: false,
  }
);

const getQueryWithCount = () =>
  queryCount.fetch({
    onSuccess: (result) => console.log(result), // { results: [ Monster, ... ], count: 200 }
  });

?count ?操作可能會很慢而且很昂貴。

如果您只想獲取沒有對象的計數(shù) - 使用Counting Objects。

要對數(shù)字和字符串等可排序類型進行排序,您可以控制返回結果的順序:

// Sorts the results in ascending order by the strength field
query.ascending("strength");

// Sorts the results in descending order by the strength field
query.descending("strength");

要在可排序類型的查詢中進行比較:

// Restricts to wins < 50
query.lessThan("wins", 50);

// Restricts to wins <= 50
query.lessThanOrEqualTo("wins", 50);

// Restricts to wins > 50
query.greaterThan("wins", 50);

// Restricts to wins >= 50
query.greaterThanOrEqualTo("wins", 50);

要檢索在值列表中匹配的對象,您可以使用 ?containsIn?,提供可接受值的數(shù)組。 這對于用單個查詢替換多個查詢通常很有用。

例如 - 如果您想檢索特定列表中任何monster所有者擁有的monster:

// Finds monsters from any of Jonathan, Dario, or Shawn
query.containedIn("ownerName", [
  "Jonathan Walsh",
  "Dario Wunsch",
  "Shawn Simon",
]);

要檢索與多個值中的任何一個都不匹配的對象,您可以使用 ?notContainedIn?,提供一個可接受值的數(shù)組。

例如,如果您想從列表中的monster所有者那里檢索monster:

// Finds monsters from anyone who is neither Jonathan, Dario, nor Shawn
query.notContainedIn("ownerName", [
  "Jonathan Walsh",
  "Dario Wunsch",
  "Shawn Simon",
]);

要檢索具有特定鍵集的對象,您可以使用 ?exists?。 相反,如果要檢索沒有特定鍵集的對象,可以使用 ?doesNotExist?。

// Finds objects that have the strength set
query.exists("strength");

// Finds objects that don't have the strength set
query.doesNotExist("strength");

獲取鍵與另一個查詢產生的一組對象中的鍵值匹配的對象。 您可以使用?matchesKeyInQuery ?方法。

例如,如果您有一個包含運動隊的類,并且您在用戶類中存儲了用戶的家鄉(xiāng),則可以發(fā)出一次查詢以查找家鄉(xiāng)球隊有獲勝記錄的用戶列表。 查詢將如下所示:

const Team = Moralis.Object.extend("Team");
const teamQuery = new Moralis.Query(Team);
teamQuery.greaterThan("winPct", 0.5);
const userQuery = new Moralis.Query(Moralis.User);
userQuery.matchesKeyInQuery("hometown", "city", teamQuery);
// results has the list of users with a hometown team with a winning record
const results = await userQuery.find();

相反,要獲取鍵與另一個查詢產生的一組對象中的鍵值不匹配的對象,請使用 ?doesNotMatchKeyInQuery?。 例如,查找家鄉(xiāng)球隊有輸球記錄的用戶:

const losingUserQuery = new Moralis.Query(Moralis.User);
losingUserQuery.doesNotMatchKeyInQuery("hometown", "city", teamQuery);
// results has the list of users with a hometown team with a losing record
const results = await losingUserQuery.find();

要根據 ?objectId ?從第二個表中的指針過濾行,可以使用點表示法:

const rolesOfTypeX = new Moralis.Query("Role");
rolesOfTypeX.equalTo("type", "x");

const groupsWithRoleX = new Moralis.Query("Group");
groupsWithRoleX.matchesKeyInQuery(
  "objectId",
  "belongsTo.objectId",
  rolesOfTypeX
);
groupsWithRoleX.find().then(function (results) {
  // results has the list of groups with role x
});

通過使用鍵列表調用 ?select ?來限制返回的字段。

例如,要檢索僅包含 ?strength ?和 ?ownerName ?字段(以及特殊的內置字段,如 ?objectId?、?createdAt ?和 ?updatedAt?)的文檔:

你可以通過?JS?、?React?來實現(xiàn)

const Monster = Moralis.Object.extend("Monster");
const query = new Moralis.Query(Monster);
query.select("strength", "ownerName");
query.find().then(function (monsters) {
  // each of the monsters will only have the selected fields available.
});
import { useMoralisQuery } from "react-moralis";

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

  const getSelectedQuery = () =>
    fetch({
      onSuccess: (monster) => {
        // each of the monsters will only have the selected fields available.
      },
    });

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

同樣,要在檢索其余字段時刪除不需要的字段,請使用 ?exclude?(可以通過?JS?、?React?來實現(xiàn)):

const Monster = Moralis.Object.extend("Monster");
const query = new Moralis.Query(Monster);
query.exclude("ownerName");
query.find().then(function (monsters) {
  // Now each monster will have all fields except `ownerName`
});
import { useMoralisQuery } from "react-moralis";

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

  const queryExcludingParam = () =>
    fetch({
      onSuccess: (monsters) => {
        // Now each monster will have all fields except `ownerName`
      },
    });

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

稍后可以通過對返回的對象調用 ?fetch ?來獲取剩余的字段:

query
  .first()
  .then(function (result) {
    // only the selected fields of the object will now be available here.
    return result.fetch();
  })
  .then(function (result) {
    // all fields of the object will now be available here.
  });

請記住在對?address?列進行查詢約束時確保?addresses?為小寫。

數(shù)組值查詢

對于數(shù)組類型的鍵,您可以通過以下方式找到鍵的數(shù)組值包含 2 的對象:

// Find objects where the array in arrayKey contains 2.
query.equalTo("arrayKey", 2);

您還可以找到鍵的數(shù)組值包含每個元素 2、3 和 4 的對象,其中包含以下內容:

// Find objects where the array in arrayKey contains all of the elements 2, 3, and 4.
query.containsAll("arrayKey", [2, 3, 4]);

儀表板中的查詢測試

注意:可以直接在“?Moralis Dashboard?”中運行查詢代碼。 可以通過導航到菜單中的“API 控制臺 > JS 控制臺”找到它。 這是一個在首次構建查詢時玩耍的好地方,因為它不需要任何設置或初始化。 它的功能與瀏覽器中的 JavaScript 控制臺完全相同,只是它可以直接訪問 Moralis SDK 和主密鑰。

完全按照您在客戶端或云代碼中的方式鍵入查詢。 包括一個 ?console.log()? 來打印結果,然后按“運行”按鈕。 需要注意的一些差異:

  • 需要使用 ?Parse ?關鍵字而不是 Moralis
    • 即新 ?Parse.Query("EthTokenTransfers")?
    • 這可能會在未來的版本中得到修復(Moralis 是 Parse 的一個分支)。
  • 不要在查詢中轉義 ?$?。
  • 您可以使用主密鑰 - ?const results = query.find({ useMasterKey: true })?

可以通過單擊“保存”在會話之間保存代碼。

字符串值查詢

從搜索開始

使用 ?startsWith ?限制以特定字符串開頭的字符串值。 與 MySQL LIKE 運算符類似,這是索引的,因此對于大型數(shù)據集很有效:

// Finds barbecue sauces that start with "Big Daddy's".
const query = new Moralis.Query(BarbecueSauce);
query.startsWith("name", "Big Daddy's");

上面的示例將匹配“name”字符串鍵中的值以“Big Daddy's”開頭的任何 BarbecueSauce 對象。 例如,“Big Daddy's”和“Big Daddy's BBQ”都會匹配,但“big daddy's”或“BBQ Sauce: Big Daddy's”不匹配。

具有正則表達式約束的查詢非常昂貴,尤其是對于超過 100,000 條記錄的類。 Moralis 限制在任何給定時間可以在特定應用程序上運行的操作數(shù)。

全文檢索

使用全文以獲得高效的搜索功能。 文本索引會自動為您創(chuàng)建。 您的字符串將轉換為標記以進行快速搜索。

注意:全文搜索可能是資源密集型的。 確保使用索引的成本物有所值。

const query = new Moralis.Query(BarbecueSauce);
query.fullText("name", "bbq");

上面的示例將匹配“name”字符串鍵中的值包含“bbq”的任何 BarbecueSauce 對象。 例如,“Big Daddy's BBQ”、“Big Daddy's bbq”和“Big BBQ Daddy”都將匹配。

// You can sort by weight / rank. ascending() and select()
const query = new Moralis.Query(BarbecueSauce);
query.fullText("name", "bbq");
query.ascending("$score");
query.select("$score");
query
  .find()
  .then(function (results) {
    // results contains a weight / rank in result.get('score')
  })
  .catch(function (error) {
    // There was an error.
  });

關系查詢

有幾種方法可以發(fā)出對關系數(shù)據的查詢。 要檢索字段與特定 ?Moralis.Object? 匹配的對象,您可以使用 ?equalTo?,就像其他數(shù)據類型一樣。

例如,如果每個 ?Comment ?在其 ?post ?字段中都有一個 ?Post ?對象,您可以獲取特定 ?Post ?的評論:

// Assume Moralis.Object myPost was previously created.
const query = new Moralis.Query(Comment);
query.equalTo("post", myPost);
// comments now contains the comments for myPost
const comments = await query.find();

要檢索字段包含匹配不同查詢的 ?Moralis.Object? 的對象,您可以使用 ?matchesQuery?。 為了查找包含圖片的帖子的評論,您可以執(zhí)行以下操作:

const Post = Moralis.Object.extend("Post");
const Comment = Moralis.Object.extend("Comment");
const innerQuery = new Moralis.Query(Post);
innerQuery.exists("image");
const query = new Moralis.Query(Comment);
query.matchesQuery("post", innerQuery);
// comments now contains the comments for posts with images.
const comments = await query.find();

要檢索字段包含不匹配不同查詢的 ?Moralis.Object? 的對象,您可以使用 ?doesNotMatchQuery?。 要查找沒有圖片的帖子的評論,您可以執(zhí)行以下操作:

const Post = Moralis.Object.extend("Post");
const Comment = Moralis.Object.extend("Comment");
const innerQuery = new Moralis.Query(Post);
innerQuery.exists("image");
const query = new Moralis.Query(Comment);
query.doesNotMatchQuery("post", innerQuery);
// comments now contains the comments for posts without images.
const comments = await query.find();

您還可以通過 ?objectId ?進行關系查詢:

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

要在一個查詢中返回多種類型的相關對象,請使用 ?include ?方法。

例如,假設您正在檢索最后 10 條評論,并且您想同時檢索他們的相關帖子:

const query = new Moralis.Query(Comment);

// Retrieve the most recent ones
query.descending("createdAt");

// Only retrieve the last ten
query.limit(10);

// Include the post data with each comment
query.include("post");

// Comments now contains the last ten comments, and the "post" field
const comments = await query.find();
// has been populated. For example:
for (let i = 0; i < comments.length; i++) {
  // This does not require a network access.
  const post = comments[i].get("post");
}

做多級包括使用點符號。 使用以下查詢。

例如,如果您想包含評論的帖子和帖子的作者,您可以這樣做:

query.include(["post.author"]);

您可以通過多次調用 ?include ?來發(fā)出包含多個字段的查詢。 此功能也適用于 ?Moralis.Query? 助手,例如 ?first ?和 ?get?。

計數(shù)對象

注意:在舊的 Moralis 托管后端中,計數(shù)查詢的速率被限制為每分鐘最多 160 個請求。 他們還為包含 1,000 多個對象的類返回了不準確的結果。 但是,Moralis Dapp 已經消除了這兩個限制,并且可以計算遠高于 1,000 個的對象。

要計算有多少對象與查詢匹配,但您不需要檢索所有匹配的對象,可以使用 ?count ?而不是 ?find?。

例如,要計算特定?monster?擁有者擁有的?monster?數(shù)量:

const Monster = Moralis.Object.extend("Monster");
const query = new Moralis.Query(Monster);
query.equalTo("ownerName", "Aegon");
const count = await query.count();
alert("Aegon has owned " + count + " monsters");

復合查詢

對于更復雜的查詢,您可能需要復合查詢。 復合查詢是子查詢的邏輯組合(例如“and”或“or”)。

注意:我們不支持復合查詢的子查詢中的 ?GeoPoint ?或非過濾約束(例如 ?near?、?withinGeoBox?、?limit?、?skip?、?ascending/descending?、?include?)。

OR-ed 查詢約束

要查找與多個查詢之一匹配的對象,您可以使用 ?Moralis.Query.or? 方法構造一個查詢,該查詢是傳入查詢的 ?OR?。

例如,如果您想找到獲得很多勝利或少數(shù)勝利的玩家,您可以執(zhí)行以下操作:

const lotsOfWins = new Moralis.Query("Player");
lotsOfWins.greaterThan("wins", 150);

const fewWins = new Moralis.Query("Player");
fewWins.lessThan("wins", 5);

const mainQuery = Moralis.Query.or(lotsOfWins, fewWins);
mainQuery
  .find()
  .then(function (results) {
    // results contains a list of players that either have won a lot of games or won only a few games.
  })
  .catch(function (error) {
    // There was an error.
  });

AND-ed 查詢約束

要查找符合所有條件的對象,通常只使用一個查詢。 您可以向新創(chuàng)建的 ?Moralis.Query? 添加額外的約束,充當?and?運算符。

const query = new Moralis.Query("User");
query.greaterThan("age", 18);
query.greaterThan("friends", 0);
query
  .find()
  .then(function (results) {
    // results contains a list of users both older than 18 and having friends.
  })
  .catch(function (error) {
    // There was an error.
  });

有時比這個簡單的示例更復雜,您可能需要子查詢的復合查詢。 您可以使用 ?Moralis.Query.and? 方法構造一個查詢,該查詢是傳入查詢的 ?AND?。

例如,如果您想查找 16 歲或 18 歲且沒有朋友或至少有兩個朋友的用戶,您可以執(zhí)行以下操作:

const age16Query = new Moralis.Query("User");
age16Query.equalTo("age", 16);

const age18Query = new Moralis.Query("User");
age18Query.equalTo("age", 18);

const friends0Query = new Moralis.Query("User");
friends0Query.equalTo("friends", 0);

const friends2Query = new Moralis.Query("User");
friends2Query.greaterThan("friends", 2);

const mainQuery = Moralis.Query.and(
  Moralis.Query.or(age16Query, age18Query),
  Moralis.Query.or(friends0Query, friends2Query)
);
mainQuery
  .find()
  .then(function (results) {
    // results contains a list of users in the age of 16 or 18 who have either no friends or at least 2 friends
    // results: (age 16 or 18) and (0 or >2 friends)
  })
  .catch(function (error) {
    // There was an error.
  });

總計的

可以使用聚合進行查詢,允許您通過一組輸入值檢索對象。 結果不會是 ?Moralis.Objects?,因為您將聚合自己的字段。

?MasterKey ?是必需的。

聚合使用階段通過將結果從一個階段傳遞到下一個階段來過濾結果。 前一階段的輸出成為下一階段的輸入。

您可以使用數(shù)組或對象創(chuàng)建管道。

const pipelineObject = {
  group: { objectId: "$name" },
};

const pipelineArray = [{ group: { objectId: "$name" } }];

有關可用階段的列表,請參閱 Mongo 聚合文檔。

注意:Mongo 聚合文檔中的大多數(shù)操作都適用于 ?Moralis Server?,但 ?_id? 不存在。 請?zhí)鎿Q為 ?objectId?。

Match

Match管道類似于equalTo。

const pipeline = [{ match: { name: "BBQ" } }];

const query = new Moralis.Query("User");

query
  .aggregate(pipeline)
  .then(function (results) {
    // results contains name that matches 'BBQ'
  })
  .catch(function (error) {
    // There was an error.
  });

您可以通過比較來匹配。

const pipeline = [{ match: { score: { $gt: 15 } } }];

const query = new Moralis.Query("User");

query
  .aggregate(pipeline)
  .then(function (results) {
    // results contains score greater than 15
  })
  .catch(function (error) {
    // There was an error.
  });

您可以在 Mongo 查詢運算符文檔中閱讀有關可用運算符的更多信息。

Lookup (Join)

lookup管道類似于 SQL 中的 LEFT OUTER JOIN。 它將匹配另一個集合中的文檔并將它們作為數(shù)組屬性帶入結果中。 

例如,在投資組合應用程序中,您可能希望顯示用戶的所有代幣交易。 在 Moralis 中,這些存儲在 ?EthTokenTransfers ?集合中。 除了令牌名稱和小數(shù)位數(shù)之外,此集合包含所需的所有信息,這些信息是在前端以一種很好的方式顯示此信息所必需的。 額外的信息在 ?EthTokenBalance ?集合中,為了得到它,我們需要查找。 有關更多詳細信息,請查看 Mongo lookup文檔。

簡單查找(單等式)

不幸的是,對于我們的用例,?EthTokenBalance ?集合不僅包含我們當前用戶的信息,還包含所有用戶的信息。 這意味著每個持有該令牌的用戶都會重復該令牌名稱。 這意味著加入多個屬性,它需要不同的語法,下面將介紹。 現(xiàn)在,假設我們有另一個名為 ?Token ?的集合,它看起來像這樣:

Token {
  objectId: string,
  token_address: string,
  symbol: string,
  name: string,
  decimals: number
}

然后你會定義一個這樣的云函數(shù)(聚合查詢必須在云代碼中運行)。

記住要像 ?\$? 一樣轉義 ?$? 以防止解析錯誤(現(xiàn)在已修復?。?。

// this goes in the Moralis server Cloud Functions section
Moralis.Cloud.define("getUserTokenTransfers", function (request) {
  const userAddress = request.params.userAddress;
  const query = new Moralis.Query("EthTokenTransfers");

  const pipeline = [
    // only transfers to or from userAddress
    {
      match: {
        $expr: {
          $or: [
            { $eq: ["$from_address", userAddress] },
            { $eq: ["$to_address", userAddress] },
          ],
        },
      },
    },

    // join to Token collection on token_address
    {
      lookup: {
        from: "Token",
        localField: "token_address",
        foreignField: "token_address",
        as: "token",
      },
    },
  ];

  return query.aggregate(pipeline);
});

輸出如下所示: “?token?”指定 ?Token ?表中匹配文檔的輸出數(shù)組的名稱。 如果連接是一對多而不是一對一,則此數(shù)組的長度將大于 1。

[
  {
    // EthTokenTransfer collection attributes
    "block_timestamp":{...}
    "token_address": "0x8762db106b2c2a0bccb3a80d1ed41273552616e8"
    "from_address": "0xba65016890709dbc9491ca7bf5de395b8441dc8b"
    "to_address": "0x29781d9fca70165cbc952b8c558d528b85541f0b"
    "value": "29803465370630263212090"
    "transaction_hash": "0xfc611dbae7c67cd938fca58a0cc2fe46d224f71b91472d4c9241e997e6440ac1"
    "token": [
      {
        // Token collection attributes from lookup
        "_id": "HKA8dzHG1A"
        "token_address": "0x8762db106b2c2a0bccb3a80d1ed41273552616e8"
        "symbol": "RSR"
        "name": "Reserve Rights"
        "decimals": 18
      }
    ]
  }
]

復雜連接(多重相等)

連接多個屬性需要在查找中使用嵌套管道,但在定義集合應如何連接時提供了更大的靈活性。 上面的查詢可以重寫以加入 ?EthTokenTranfers ?和 ?EthTokenBalance?。

// this goes in the Moralis server Cloud Functions section
Moralis.Cloud.define("getUserTokenTransfers", function(request) {
  const userAddress = request.params.userAddress;
  const query = new Moralis.Query("EthTokenTransfers");

  const pipeline = [
    // only transfers to or from userAddress
    {match: {$expr: {$or: [
      {$eq: ["$from_address", userAddress]},
      {$eq: ["$to_address", userAddress]},
    ]}}},

      // join to EthTokenBalance on token_address and userAddress
    {lookup: {
      from: "EthTokenBalance",
      let: { tokenAddress: "$token_address", userAddress: userAddress},
      pipeline: [
        {$match: {$expr: {$and: [
          { $eq: ["$token_address", "$tokenAddress"] },
          { $eq: ["$address", "$userAddress"] },
      ]}}],
      as: "EthTokenBalance",
    }}
  ];

  return query.aggregate(pipeline);
});

lookup管道使用匹配階段來指定其他連接條件。 另外,請注意 let 定義了查找管道要使用的變量。 這是必需的,因為查找管道無法直接訪問原始集合中的屬性。 有關詳細信息,請參閱 MongoDB $lookup 文檔中的“使用 $lookup 指定多個連接條件”部分。

項目(選擇)

項目管道類似于鍵或選擇、添加或刪除現(xiàn)有字段。

const pipeline = [{ project: { name: 1 } }];

const query = new Moralis.Query("User");

query
  .aggregate(pipeline)
  .then(function (results) {
    // results contains only name field
  })
  .catch(function (error) {
    // There was an error.
  });

Group

組管道類似于不同的。

您可以按字段分組:

// score is the field. $ before score lets the database know this is a field
const pipeline = [{ group: { objectId: "$score" } }];

const query = new Moralis.Query("User");

query
  .aggregate(pipeline)
  .then(function (results) {
    // results contains unique score values
  })
  .catch(function (error) {
    // There was an error.
  });

您可以應用集體計算,如 $sum、$avg、$max、$min。

// total will be a newly created field to hold the sum of score field
const pipeline = [{ group: { objectId: null, total: { $sum: "$score" } } }];

const query = new Moralis.Query("User");

query
  .aggregate(pipeline)
  .then(function (results) {
    // results contains sum of score field and stores it in results[0].total
  })
  .catch(function (error) {
    // There was an error.
  });

如果要對包含數(shù)值但它們作為字符串存儲在數(shù)據庫中的列執(zhí)行計算,則必須將值轉換為數(shù)值數(shù)據類型。 例如,存儲在字符串列中的 uint256 應使用 ?$toLong? 進行轉換。

 { group: { objectId: '$nftItem',  priceOfAllNfts: { $sum: {$toLong : '$price'} } } },

可以使用 ?$$ROOT? 訪問與分組字段匹配的文檔集合,并且可以使用 ?$push? 累加器將其推送到數(shù)組中。

// games will be an array of all the games played by each unique player
const pipeline = [
  { group: { objectId: "$playerId", games: { $push: "$ROOT" } } },
];

const query = new Moralis.Query("GameRound");

query
  .aggregate(pipeline)
  .then(function (results) {
    // results contains a collection of players with their respective games played
  })
  .catch(function (error) {
    // There was an error.
  });

您可以使用點表示法按子文檔的列進行分組。 但是,您必須將其括在引號中。

 { group: { objectId: '$player.username',  games: { $push: "$ROOT" } } },

Sort

排序階段用于按給定列按特定順序對結果進行排序。

指定排序順序,1 用于升序排序,-1 用于降序排序。

// This will sort the rows in ascending order based on the username field
{
  sort: {
    username: 1;
  }
}

您可以按給定順序按幾列排序。

 // This will sort the rows in ascending order based on the country field,
 // and then in descending order on the city field
 { sort : { country: 1, city: -1 } }

skip

跳過階段跳過傳遞到該階段的指定行數(shù)。 這通常在實現(xiàn)分頁功能時使用。

// This stage will skip the first 5 rows passed into this stage
{
  skip: 5;
}

Limit

限制階段僅包括傳入該階段的前 n 行。

// This stage will throw away all rows except the first 5
{
  limit: 5;
}

Count

count 階段返回傳遞到分配給變量名稱的階段的行數(shù)。

// This stage will return the number of rows passed into the stage
// and store it in the variable numberOfNfts
{
  count: "numberOfNfts";
}

Distinct

可以使用 distinct 進行查詢,允許您找到指定字段的唯一值。

?MasterKey ?是必需的。

const query = new Moralis.Query("User");

query
  .distinct("age")
  .then(function (results) {
    // results contains unique age
  })
  .catch(function (error) {
    // There was an error.
  });

您還可以使用 ?equalTo ?限制結果。

const query = new Moralis.Query("User");
query.equalTo("name", "foo");
query
  .distinct("age")
  .then(function (results) {
    // results contains unique age where name is foo
  })
  .catch(function (error) {
    // There was an error.
  });

閱讀偏好

使用 MongoDB 副本集時,您可以使用 ?query.readPreference(readPreference, includeReadPreference, subqueryReadPreference)? 函數(shù)來選擇將從哪個副本中檢索對象。 ?includeReadPreference ?參數(shù)選擇從哪個副本中檢索包含的指針,而 ?subqueryReadPreference ?參數(shù)選擇子查詢將在哪個副本中運行。 可能的值為 ?PRIMARY?(默認)、?PRIMARY_PREFERRED?、?SECONDARY?、?SECONDARY_PREFERRED ?或 ?NEAREST?。 如果未傳遞 ?includeReadPreference ?參數(shù),則為 ?readPreference ?選擇的相同副本也將用于包含。 相同的規(guī)則適用于 ?subqueryReadPreference ?參數(shù)。

query.readPreference("SECONDARY", "SECONDARY_PREFERRED", "NEAREST");


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號