9 minutes
GraphQL API
Learn about the GraphQL Query API used in The Graph.
What is GraphQL?
GraphQL is a query language for APIs and a runtime for executing those queries with your existing data. The Graph uses GraphQL to query subgraphs.
To understand the larger role that GraphQL plays, review developing and creating a subgraph.
Queries with GraphQL
In your subgraph schema you define types called Entities
. For each Entity
type, entity
and entities
fields will be generated on the top-level Query
type.
Note: query
does not need to be included at the top of the graphql
query when using The Graph.
Exempel
Query for a single Token
entity defined in your schema:
{ token(id: "1") { id owner }}
Note: When querying for a single entity, the id
field is required, and it must be written as a string.
Query all Token
entities:
{ tokens { id owner }}
Sortering
When querying a collection, you may:
- Use the
orderBy
parameter to sort by a specific attribute. - Use the
orderDirection
to specify the sort direction,asc
for ascending ordesc
for descending.
Exempel
{ tokens(orderBy: price, orderDirection: asc) { id owner }}
Exempel på sortering av nästlade entiteter
As of Graph Node v0.30.0
entities can be sorted on the basis of nested entities.
The following example shows tokens sorted by the name of their owner:
{ tokens(orderBy: owner__name, orderDirection: asc) { id owner { name } }}
Currently, you can sort by one-level deep String
or ID
types on @entity
and @derivedFrom
fields. Unfortunately, sorting by interfaces on one level-deep entities, sorting by fields which are arrays and nested entities is not yet supported.
Paginering
When querying a collection, it’s best to:
- Use the
first
parameter to paginate from the beginning of the collection.- The default sort order is by
ID
in ascending alphanumeric order, not by creation time.
- The default sort order is by
- Use the
skip
parameter to skip entities and paginate. For instance,first:100
shows the first 100 entities andfirst:100, skip:100
shows the next 100 entities. - Avoid using
skip
values in queries because they generally perform poorly. To retrieve a large number of items, it’s best to page through entities based on an attribute as shown in the previous example above.
Example using first
Fråga efter de första 10 tokens:
{ tokens(first: 10) { id owner }}
To query for groups of entities in the middle of a collection, the skip
parameter may be used in conjunction with the first
parameter to skip a specified number of entities starting at the beginning of the collection.
Example using first
and skip
Query 10 Token
entities, offset by 10 places from the beginning of the collection:
{ tokens(first: 10, skip: 10) { id owner }}
Example using first
and id_ge
If a client needs to retrieve a large number of entities, it’s more performant to base queries on an attribute and filter by that attribute. For example, a client could retrieve a large number of tokens using this query:
query manyTokens($lastID: String) { tokens(first: 1000, where: { id_gt: $lastID }) { id owner }}
The first time, it would send the query with lastID = ""
, and for subsequent requests it would set lastID
to the id
attribute of the last entity in the previous request. This approach will perform significantly better than using increasing skip
values.
Filtrering
- You can use the
where
parameter in your queries to filter for different properties. - You can filter on multiple values within the
where
parameter.
Example using where
Query challenges with failed
outcome:
{ challenges(where: { outcome: "failed" }) { challenger outcome application { id } }}
You can use suffixes like _gt
, _lte
for value comparison:
Exempel på filtrering av intervall
{ applications(where: { deposit_gt: "10000000000" }) { id whitelisted deposit }}
Exempel på blockfiltrering
You can also filter entities that were updated in or after a specified block with _change_block(number_gte: Int)
.
Detta kan vara användbart om du bara vill hämta enheter som har ändrats, till exempel sedan den senaste gången du pollade. Eller alternativt kan det vara användbart för att undersöka eller felsöka hur enheter förändras i din undergraf (om det kombineras med ett blockfilter kan du isolera endast enheter som ändrades i ett visst block).
{ applications(where: { _change_block: { number_gte: 100 } }) { id whitelisted deposit }}
Exempel på filtrering av inbäddade entiteter
Filtering on the basis of nested entities is possible in the fields with the _
suffix.
Detta kan vara användbart om du vill hämta endast entiteter vars entiteter på barnnivå uppfyller de angivna villkoren.
{ challenges(where: { application_: { id: 1 } }) { challenger outcome application { id } }}
Logiska operatorer
As of Graph Node v0.30.0
you can group multiple parameters in the same where
argument using the and
or the or
operators to filter results based on more than one criteria.
AND
Operator
The following example filters for challenges with outcome
succeeded
and number
greater than or equal to 100
.
{ challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) { challenger outcome application { id } }}
Syntactic sugar: You can simplify the above query by removing the and
operator by passing a sub-expression separated by commas.
{ challenges(where: { number_gte: 100, outcome: "succeeded" }) { challenger outcome application { id } }}
OR
Operator
The following example filters for challenges with outcome
succeeded
or number
greater than or equal to 100
.
{ challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) { challenger outcome application { id } }}
Note: When constructing queries, it is important to consider the performance impact of using the or
operator. While or
can be a useful tool for broadening search results, it can also have significant costs. One of the main issues with or
is that it can cause queries to slow down. This is because or
requires the database to scan through multiple indexes, which can be a time-consuming process. To avoid these issues, it is recommended that developers use and operators instead of or whenever possible. This allows for more precise filtering and can lead to faster, more accurate queries.
Alla filter
Fullständig lista över parametersuffix:
__not_gt_lt_gte_lte_in_not_in_contains_contains_nocase_not_contains_not_contains_nocase_starts_with_starts_with_nocase_ends_with_ends_with_nocase_not_starts_with_not_starts_with_nocase_not_ends_with_not_ends_with_nocase
Please note that some suffixes are only supported for specific types. For example, Boolean
only supports _not
, _in
, and _not_in
, but _
is available only for object and interface types.
In addition, the following global filters are available as part of where
argument:
_change_block(number_gte: Int)
Tidsreseförfrågningar
You can query the state of your entities not just for the latest block, which is the default, but also for an arbitrary block in the past. The block at which a query should happen can be specified either by its block number or its block hash by including a block
argument in the toplevel fields of queries.
The result of such a query will not change over time, i.e., querying at a certain past block will return the same result no matter when it is executed, with the exception that if you query at a block very close to the head of the chain, the result might change if that block turns out to not be on the main chain and the chain gets reorganized. Once a block can be considered final, the result of the query will not change.
Note: The current implementation is still subject to certain limitations that might violate these guarantees. The implementation can not always tell that a given block hash is not on the main chain at all, or if a query result by a block hash for a block that is not yet considered final could be influenced by a block reorganization running concurrently with the query. They do not affect the results of queries by block hash when the block is final and known to be on the main chain. This issue explains what these limitations are in detail.
Exempel
{ challenges(block: { number: 8000000 }) { challenger outcome application { id } }}
This query will return Challenge
entities, and their associated Application
entities, as they existed directly after processing block number 8,000,000.
Exempel
{ challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) { challenger outcome application { id } }}
This query will return Challenge
entities, and their associated Application
entities, as they existed directly after processing the block with the given hash.
Fulltextsökförfrågningar
Fulltext search query fields provide an expressive text search API that can be added to the subgraph schema and customized. Refer to Defining Fulltext Search Fields to add fulltext search to your subgraph.
Fulltext search queries have one required field, text
, for supplying search terms. Several special fulltext operators are available to be used in this text
search field.
Fulltextsökoperatorer:
Symbol | Operatör | Beskrivning |
---|---|---|
& | And | För att kombinera flera söktermer till ett filter för entiteter som inkluderar alla de angivna termerna |
| | Or | Förfrågningar med flera söktermer separerade av ellipsen kommer att returnera alla entiteter med en matchning från någon av de angivna termerna |
<-> | Follow by | Ange avståndet mellan två ord. |
:* | Prefix | Använd prefixsöktermen för att hitta ord vars prefix matchar (2 tecken krävs.) |
Exempel
Using the or
operator, this query will filter to blog entities with variations of either “anarchism” or “crumpet” in their fulltext fields.
{ blogSearch(text: "anarchism | crumpets") { id title body author }}
The follow by
operator specifies a words a specific distance apart in the fulltext documents. The following query will return all blogs with variations of “decentralize” followed by “philosophy”
{ blogSearch(text: "decentralized <-> philosophy") { id title body author }}
Kombinera fulltextoperatorer för att skapa mer komplexa filter. Med en pretext-sökoperatör kombinerad med en follow by kommer detta exempel att matcha alla bloggenheter med ord som börjar med “lou” följt av “music”.
{ blogSearch(text: "lou:* <-> music") { id title body author }}
Validering
Graph Node implements specification-based validation of the GraphQL queries it receives using graphql-tools-rs, which is based on the graphql-js reference implementation. Queries which fail a validation rule do so with a standard error - visit the GraphQL spec to learn more.
Schema
The schema of your dataSources, i.e. the entity types, values, and relationships that are available to query, are defined through the GraphQL Interface Definition Language (IDL).
GraphQL schemas generally define root types for queries
, subscriptions
and mutations
. The Graph only supports queries
. The root Query
type for your subgraph is automatically generated from the GraphQL schema that’s included in your subgraph manifest.
Note: Our API does not expose mutations because developers are expected to issue transactions directly against the underlying blockchain from their applications.
Entiteter
All GraphQL types with @entity
directives in your schema will be treated as entities and must have an ID
field.
Note: Currently, all types in your schema must have an @entity
directive. In the future, we will treat types without an @entity
directive as value objects, but this is not yet supported.
Metadata för undergrafer
All subgraphs have an auto-generated _Meta_
object, which provides access to subgraph metadata. This can be queried as follows:
{ _meta(block: { number: 123987 }) { block { number hash timestamp } deployment hasIndexingErrors }}
Om ett block anges är metadata från det blocket, om inte används det senast indexerade blocket. Om det anges måste blocket vara efter undergrafens startblock och mindre än eller lika med det senast indexerade blocket.
deployment
is a unique ID, corresponding to the IPFS CID of the subgraph.yaml
file.
block
provides information about the latest block (taking into account any block constraints passed to _meta
):
- hash: blockets hash
- nummer: blockets nummer
- timestamp: blockets timestamp, om tillgänglig (detta är för närvarande endast tillgängligt för undergrafer som indexerar EVM-nätverk)
hasIndexingErrors
is a boolean identifying whether the subgraph encountered indexing errors at some past block