GraphQL 架構(GraphQL Schema)

定義實體(Defining Entities)

schema.graphql 文件定義了各種 GraphQL 架構。 由于 GraphQL 查詢語言的工作方式,模式文件本質上決定了來自 SubQuery 的數據的形狀, 要了解有關如何使用 GraphQL 架構語言編寫的更多資訊,我們建議查看架構和類型(https://graphql.org/learn/schema/#type-language)

重要提示:當您對架構文件(schema file)進行任何更改時,請確保使用 yarn codegen 代碼來生成重新生成類型目錄,

實體(Entities)

每個實體(entity)都必須定義它的必填字段id與ID的類型!它用作主鍵,并且在所有相同類型的實體中是唯一的。

實體(entity)中不可為空的字段由“ ! ”來表示。 請看下面的例子:

type Example @entity { id: ID! # id field is always required and must look like this name: String! # This is a required field address: String # This is an optional field }

支持的標量和類型(Supported scalars and types)

我們目前支持流動標量類型:

• ID

• Int

• String

• BigInt

• Date

• Boolean

用于嵌套關系實體,您可以使用定義的實體名稱作為字段之一。 請參閱實體關系(https://doc.subquery.network/create/graphql.html#entity-relationships),

• JSON 也可以存儲結構化數據,請參閱 JSON 類型(https://doc.subquery.network/create/graphql.html#json-type)。

按非主鍵字段進行索引(Indexing by non-primary-key field)

為了提高查詢性能,只需在非主鍵字段上執行 @index 注釋即可索引實體字段。

但是,我們不允許用戶在任何 JSON 對象上添加 @index 注釋, 默認情況下,索引會自動添加到外鍵和資料庫中的 JSON 字段,但只是為了增強查詢服務性能。

這有一個例子。

type User @entity { id: ID! name: String! @index(unique: true) # unique can be set to true or false title: Title! # Indexes are automatically added to foreign key field } type Title @entity { id: ID! name: String! @index(unique:true) }

假設我們知道這個用戶的名字,但我們不知道確切的 id 值,我們可以在名稱字段后面添加@index,而不是提取所有用戶然后按名稱過濾, 這使得查詢速度更快,我們還可以添加 unique: true 以確保唯一性,

如果字段不唯一,則最大結果集為 100

當代碼生成運行時,這將自動在 User 模型下創建一個 getByName,然后外鍵字段 title 將創建一個 getByTitleId 方法,這兩者都可以在映射函數中直接訪問。

/* Prepare a record for title entity */ INSERT INTO titles (id, name) VALUES (‘id_1’, ‘Captain’)

// Handler in mapping function import {User} from “../types/models/User” import {Title} from “../types/models/Title” const jack = await User.getByName(‘Jack Sparrow’); const captainTitle = await Title.getByName(‘Captain’); const pirateLords = await User.getByTitleId(captainTitle.id); // List of all Captains

實體關系(Entity Relationships)

一個實體(entity)通常與其他實體(entity)有嵌套關系。 默認情況下,將字段值設置為另一個實體(entity)名稱將定義這兩個實體(entity)之間的一對一關系,

可以使用以下示例配置不同的實體(entity)關系(一對一、一對多和多對多)。

  • 一對一關系(One-to-One Relationships)

當只有一個實體映射到另一個實體時,一對一關系是默認的,

例子:一本護照只屬于一個人,一個人只有一本護照(在這個例子中):

type Person @entity { id: ID! } type Passport @entity { id: ID! owner: Person! }

或者

type Person @entity { id: ID! passport: Passport! } type Passport @entity { id: ID! owner: Person! }

  • 一對多關系(One-to-Many relationships)

您可以使用方括號表示一個字段類型包括多個實體。

示例:一個人可以擁有多個帳戶,

type Person @entity { id: ID! accounts: [Account] } type Account @entity { id: ID! publicAddress: String! }

  • 多對多關系(Many-to-Many relationships)

多對多關系可以通過實現一個映射實體(mapping entity)來連接其他兩個實體(entity)來實現。

示例:每個人都是多個組 (PersonGroup) 的一部分,并且組有多個不同的人 (PersonGroup)。

type Person @entity { id: ID! name: String! groups: [PersonGroup] } type PersonGroup @entity { id: ID! person: Person! Group: Group! } type Group @entity { id: ID! name: String! persons: [PersonGroup] }

此外,可以在中間實體(entity)的多個字段中創建同一實體(entity)的連接。

例如,一個賬戶可以實現多次轉賬,每次轉賬都有一個源賬戶和目的地賬戶。

這將通過 Transfer 層在兩個 Accounts(from 和 to)之間建立雙向關系,

type Account @entity { id: ID! publicAddress: String! } type Transfer @entity { id: ID! amount: BigInt from: Account! to: Account! }

反向查找(Reverse Lookups)

為了使一個實體(entity)能夠反向查詢到一個關系,請將 @derivedFrom 附加到該字段并指向另一個實體(entity)的反向查找字段,

這會在可以查詢的實體(entity)上創建一個虛擬字段,

通過將 sentTransfer 或 receivedTransfer 設置為從相應的 from 或 to 字段得出的值,可以從帳戶實體中訪問“來自” 賬戶的轉移。

type Account @entity { id: ID! publicAddress: String! sentTransfers: [Transfer] @derivedFrom(field: “from”) receivedTransfers: [Transfer] @derivedFrom(field: “to”) } type Transfer @entity { id: ID! amount: BigInt from: Account! to: Account! }

JSON 類型(JSON type)

我們支持將數據保存為 JSON 類型(JSON type),這是一種存儲結構化數據的快速方式, 我們將自動生成相應的 JSON 接口來查詢這些數據,并節省您定義和管理實體(entities)的時間。

我們建議用戶在以下場景中使用 JSON 類型:

• 在單個字段中存儲結構化數據比創建多個單獨的實體(entities)更易于管理。

• 保存任意鍵/值用戶首選項(其中值可以是布爾值、文本或數字,并且不用為不同的數據類型設置單獨的列)

• 架構是不穩定的并且經常變化

定義 JSON 指令(Define JSON directive)

通過在實體中添加 jsonField 注釋,將該屬性定義為 JSON 類型, 這將自動為您項目中 types/interfaces.ts 下的所有 JSON 對象生成接口,您也可以在映射函數中訪問它們。

與實體不同,jsonField 指令對象不需要任何 id 字段。 JSON 對象還可以與其他 JSON 對象嵌套。

type AddressDetail @jsonField { street: String! district: String! } type ContactCard @jsonField { phone: String! address: AddressDetail # Nested JSON } type User @entity { id: ID! contact: [ContactCard] # Store a list of JSON objects }

查詢 JSON 字段(Querying JSON fields)

使用 JSON 類型的缺點是過濾時對查詢效率的影響很小,因為每次執行文本搜索時,都是針對整個實體來進行的,

但是,在我們的查詢服務中,影響仍然可以接受。 下面是一個示例,說明如何在 GraphQL 查詢中對 JSON 字段使用 contains 運算符來查找擁有包含“0064”的電話號碼的前 5 個用戶,

#To find the the first 5 users own phone numbers contains ‘0064’. query{ user( first: 5, filter: { contactCard: { contains: [{ phone: “0064” }] } }){ nodes{ id contactCard } } }

0 条回复 A文章作者 M管理員
    暫無討論,說說你的看法吧