subgraphs > Developing > Creating > The Graph QL Schema

The Graph QL Schema

Reading time: 8 min

Genel Bakış

Bu bölüme bağlantı

The schema for your subgraph is in the file schema.graphql. GraphQL schemas are defined using the GraphQL interface definition language.

Note: If you've never written a GraphQL schema, it is recommended that you check out this primer on the GraphQL type system. Reference documentation for GraphQL schemas can be found in the GraphQL API section.

Varlıkları Tanımlama

Bu bölüme bağlantı

Varlıkları tanımlamadan önce, verilerinizin nasıl yapılandırıldığını ve nasıl bağlantılı olduğunu düşünmek önemlidir.

  • All queries will be made against the data model defined in the subgraph schema. As a result, the design of the subgraph schema should be informed by the queries that your application will need to perform.
  • Varlıkları, olaylar veya fonksiyonlar yerine “veri içeren nesneler” olarak düşünmek faydalı olabilir.
  • You define entity types in schema.graphql, and Graph Node will generate top-level fields for querying single instances and collections of that entity type.
  • Each type that should be an entity is required to be annotated with an @entity directive.
  • Varsayılan olarak, varlıklar değiştirilebilirdir; yani, eşlemeler halihazırda mevcut varlıkları yükleyebilir, onları modifiye edebilir ve o varlığın yeni bir sürümünü saklayabilir.
    • Mutability comes at a price, so for entity types that will never be modified, such as those containing data extracted verbatim from the chain, it is recommended to mark them as immutable with @entity(immutable: true).
    • Varlığın oluşturulduğu blok içinde değişiklikler gerçekleşirse, eşlemeler değişmez varlıkları değiştirebilir. Değişmez varlıklar çok daha hızlı yazılabilir ve sorgulanabilir olduğundan, mümkün olduğunca kullanılmaları önerilir.

İyi Bir Örnek

Bu bölüme bağlantı

The following Gravatar entity is structured around a Gravatar object and is a good example of how an entity could be defined.

type Gravatar @entity(immutable: true) {
id: Bytes!
owner: Bytes
displayName: String
imageUrl: String
accepted: Boolean
}

Kötü Bir Örnek

Bu bölüme bağlantı

The following example GravatarAccepted and GravatarDeclined entities are based around events. It is not recommended to map events or function calls to entities 1:1.

type GravatarAccepted @entity {
id: Bytes!
owner: Bytes
displayName: String
imageUrl: String
}
type GravatarDeclined @entity {
id: Bytes!
owner: Bytes
displayName: String
imageUrl: String
}

Opsiyonel ve Zorunlu Alanlar

Bu bölüme bağlantı

Entity fields can be defined as required or optional. Required fields are indicated by the ! in the schema. If the field is a scalar field, you get an error when you try to store the entity. If the field references another entity then you get this error:

Null value resolved for non-null field 'name'

Each entity must have an id field, which must be of type Bytes! or String!. It is generally recommended to use Bytes!, unless the id contains human-readable text, since entities with Bytes! id's will be faster to write and query as those with a String! id. The id field serves as the primary key, and needs to be unique among all entities of the same type. For historical reasons, the type ID! is also accepted and is a synonym for String!.

For some entity types the id for Bytes! is constructed from the id's of two other entities; that is possible using concat, e.g., let id = left.id.concat(right.id) to form the id from the id's of left and right. Similarly, to construct an id from the id of an existing entity and a counter count, let id = left.id.concatI32(count) can be used. The concatenation is guaranteed to produce unique id's as long as the length of left is the same for all such entities, for example, because left.id is an Address.

Gömülü Skaler(Scalar) Türler

Bu bölüme bağlantı

GraphQL'in Desteklediği Skalerler

Bu bölüme bağlantı

GraphQL API'sinde desteklenen skalarlardan bazıları şunlardır:

TürTanım
BytesByte dizisi, onaltılık bir dizgi olarak temsil edilir. Ethereum hash değerleri ve adresleri için yaygın olarak kullanılır.
StringScalar for string values. Null characters are not supported and are automatically removed.
BooleanScalar for boolean values.
IntThe GraphQL spec defines Int to be a signed 32-bit integer.
Int8An 8-byte signed integer, also known as a 64-bit signed integer, can store values in the range from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. Prefer using this to represent i64 from ethereum.
BigIntLarge integers. Used for Ethereum's uint32, int64, uint64, ..., uint256 types. Note: Everything below uint32, such as int32, uint24 or int8 is represented as i32.
BigDecimalBigDecimal High precision decimals represented as a significand and an exponent. The exponent range is from −6143 to +6144. Rounded to 34 significant digits.
TimestampIt is an i64 value in microseconds. Commonly used for timestamp fields for timeseries and aggregations.

Numaralandırmalar

Bu bölüme bağlantı

Ayrıca bir şema içinde numaralandırmalar da oluşturabilirsiniz. Numaralandırmalar aşağıdaki sözdizimine sahiptir:

enum TokenStatus {
OriginalOwner
SecondOwner
ThirdOwner
}

Once the enum is defined in the schema, you can use the string representation of the enum value to set an enum field on an entity. For example, you can set the tokenStatus to SecondOwner by first defining your entity and subsequently setting the field with entity.tokenStatus = "SecondOwner". The example below demonstrates what the Token entity would look like with an enum field:

More detail on writing enums can be found in the GraphQL documentation.

Varlık İlişkileri

Bu bölüme bağlantı

Bir varlık, şemanızdaki bir veya daha fazla başka varlıkla ilişkili olabilir. Bu ilişkiler, sorgularınızda çaprazlanabilir. Graph'taki ilişkiler tek yönlüdür. İki yönlü ilişkileri simüle etmek, ilişkinin herhangi biri "son" üzerinde tek yönlü bir ilişki tanımlayarak mümkündür.

İlişkiler, belirtilen türün başka bir varlığın türü olması dışında, diğer tüm alanlarda olduğu gibi varlıklar üzerinde tanımlanır.

Bire Bir İlişkiler

Bu bölüme bağlantı

Define a Transaction entity type with an optional one-to-one relationship with a TransactionReceipt entity type:

type Transaction @entity(immutable: true) {
id: Bytes!
transactionReceipt: TransactionReceipt
}
type TransactionReceipt @entity(immutable: true) {
id: Bytes!
transaction: Transaction
}

Birden Çoğa İlişkiler

Bu bölüme bağlantı

Define a TokenBalance entity type with a required one-to-many relationship with a Token entity type:

type Token @entity(immutable: true) {
id: Bytes!
}
type TokenBalance @entity {
id: Bytes!
amount: Int!
token: Token!
}

Tersine Aramalar

Bu bölüme bağlantı

Reverse lookups can be defined on an entity through the @derivedFrom field. This creates a virtual field on the entity that may be queried but cannot be set manually through the mappings API. Rather, it is derived from the relationship defined on the other entity. For such relationships, it rarely makes sense to store both sides of the relationship, and both indexing and query performance will be better when only one side is stored and the other is derived.

Birden çoğa ilişkileriiçin, ilişki her zaman 'birden' tarafında depolanmalı ve her zaman 'çoğa' tarafında türetilmelidir. İlişkinin 'çoğa' tarafında bir dizi varlık depolamak yerine bu şekilde saklanması, subgraph indeksleme ve sorgulaması adına önemli ölçüde daha iyi performans sağlayacaktır. Genel olarak, varlık dizilerini depolamaktan mümkün olduğunca sakınılması gerekmektedir.

We can make the balances for a token accessible from the token by deriving a tokenBalances field:

type Token @entity(immutable: true) {
id: Bytes!
tokenBalances: [TokenBalance!]! @derivedFrom(field: "token")
}
type TokenBalance @entity {
id: Bytes!
amount: Int!
token: Token!
}

Çoktan Çoğa İlişkiler

Bu bölüme bağlantı

Kullanıcıların her birinin birden çok kuruluşa mensup olabileceği gibi çoktan çoğa ilişkilerde, ilişkiyi modellemenin en basit fakat pek verimli olmayan yolu, ilişkide yer alan iki varlıkta da bir dizi olarak saklamaktır. İlişki simetrik ise, ilişkinin yalnızca bir tarafının saklanması gerekir ve diğer taraf türetilebilir.

Define a reverse lookup from a User entity type to an Organization entity type. In the example below, this is achieved by looking up the members attribute from within the Organization entity. In queries, the organizations field on User will be resolved by finding all Organization entities that include the user's ID.

type Organization @entity {
id: Bytes!
name: String!
members: [User!]!
}
type User @entity {
id: Bytes!
name: String!
organizations: [Organization!]! @derivedFrom(field: "members")
}

A more performant way to store this relationship is through a mapping table that has one entry for each User / Organization pair with a schema like

type Organization @entity {
id: Bytes!
name: String!
members: [UserOrganization!]! @derivedFrom(field: "organization")
}
type User @entity {
id: Bytes!
name: String!
organizations: [UserOrganization!] @derivedFrom(field: "user")
}
type UserOrganization @entity {
id: Bytes! # Set to `user.id.concat(organization.id)`
user: User!
organization: Organization!
}

Bu yaklaşım, örneğin kullanıcılar için kuruluşları almak için sorguların ek bir seviyeye inmesini gerektirir:

query usersWithOrganizations {
users {
organizations {
# this is a UserOrganization entity
organization {
name
}
}
}
}

Çoktan çoğa ilişkileri depolamanın daha ayrıntılı bu yolu, subgraph için depolanan veri miktarının azalmasına ve bu sonucunda genellikle indekslenmesi ve sorgulanması önemli ölçüde daha hızlı olan bir subgraph sağlayacaktır.

Şemaya notlar/yorumlar ekleme

Bu bölüme bağlantı

As per GraphQL spec, comments can be added above schema entity attributes using the hash symbol #. This is illustrated in the example below:

type MyFirstEntity @entity {
# # varlığın benzersiz tanımlayıcısı ve birincil anahtarı
id: Bytes!
address: Bytes!
}

Tam Metinde Arama Alanlarını Tanımlama

Bu bölüme bağlantı

Tam metinde arama sorguları, metin arama girdisine dayanarak varlıkları filtreler ve sıralar. Tam metin sorguları, sorgu metni girişini indekslenmiş metin verileriyle karşılaştırmadan önce köklere işleyerek benzer kelimeler için eşleşmeler döndürebilir.

Tam metin sorgusu tanımı, sorgu adı, metin alanlarını işlemek için kullanılan dil sözlüğü, sonuçları sıralamak için kullanılan sıralama algoritması ve aramaya dahil edilen alanları içerir. Her tam metin sorgusu birden fazla alana yayılabilir, ancak dahil edilen tüm alanlar tek bir varlık türünden olmalıdır.

To add a fulltext query, include a _Schema_ type with a fulltext directive in the GraphQL schema.

type _Schema_
@fulltext(
name: "bandSearch"
language: en
algorithm: rank
include: [{ entity: "Band", fields: [{ name: "name" }, { name: "description" }, { name: "bio" }] }]
)
type Band @entity {
id: Bytes!
name: String!
description: String!
bio: String
wallet: Address
labels: [Label!]!
discography: [Album!]!
members: [Musician!]!
}

The example bandSearch field can be used in queries to filter Band entities based on the text documents in the name, description, and bio fields. Jump to GraphQL API - Queries for a description of the fulltext search API and more example usage.

query {
bandSearch(text: "breaks & electro & detroit") {
id
name
description
wallet
}
}

Feature Management: From specVersion 0.0.4 and onwards, fullTextSearch must be declared under the features section in the subgraph manifest.

Desteklenen diller

Bu bölüme bağlantı

Farklı bir dil seçmek, tam metin arama API'sı üzerinde bazen az olsa da kesin bir etkiye sahip olacaktır. Tam metin sorgu alanı tarafından kapsanan alanlar, seçilen dile bağlı olarak incelenir, bu nedenle analiz ve arama sorguları tarafından üretilen sözlükbirimleri dilden dile değişir. Örneğin: desteklenen Türkçe sözlük kullanıldığında "token" kelimesi "toke" olarak kök alınırken, elbette İngilizce sözlük "token" olarak kök alacaktır.

Desteklenen dil sözlükleri:

CodeSözlük
yalınGeneral
daDanish
nlDutch
enEnglish
fiFinnish
frFrench
deGerman
huHungarian
itItalian
noNorwegian
ptPortekizce
roRomanian
ruRussian
esSpanish
svSwedish
trTurkish

Algoritmaları Sıralama

Bu bölüme bağlantı

Sonuçları sıralamak için desteklenen algoritmalar:

AlgorithmDescription
rankSonuçları sıralamak için tam metin sorgusunun eşleştirme kalitesini (0-1) kullanın.
proximityRankSimilar to rank but also includes the proximity of the matches.
Sayfayı Düzenle

Önceki
Subgraph Manifest
Sonraki
Writing AssemblyScript Mappings
Sayfayı Düzenle