subgraphs > Querying > API GraphQL

API GraphQL

Reading time: 10 min

Learn about the GraphQL Query API used in The Graph.

Qu'est-ce que GraphQL ?

Lien vers cette section

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

Lien vers cette section

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.

Requête pour une seule entité Token définie dans votre schéma :

{
token(id: "1") {
id
owner
}
}

Note: When querying for a single entity, the id field is required, and it must be writen as a string.

Interrogez toutes les entités Token :

{
tokens {
id
owner
}
}

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 or desc for descending.
{
tokens(orderBy : price, orderDirection : asc) {
id
propriétaire
}
}

Exemple de tri d'entités imbriquées

Lien vers cette section

Depuis Graph Node v0.30.0, les entités peuvent être triées sur la base d'entités imbriquées.

The following example shows tokens sorted by the name of their owner:

{
jetons (orderBy : propriétaire__nom, orderDirection : asc) {
identifiant
propriétaire {
{
name
}
}
}
}

Actuellement, vous pouvez trier par types String ou ID profonds à un niveau sur les champs @entity et @derivedFrom. Malheureusement, le tri par interfaces sur des entités d'un seul niveau, le tri par champs qui sont des tableaux et des entités imbriquées est pas encore pris en charge.

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.
  • Use the skip parameter to skip entities and paginate. For instance, first:100 shows the first 100 entities and first: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.

Exemple utilisant first

Lien vers cette section

Interroger les 10 premiers tokens :

{
tokens(first: 10) {
id
owner
}
}

Pour rechercher des groupes d'entités au milieu d'une collection, le paramètre skip peut être utilisé conjointement avec le paramètre first pour ignorer un nombre spécifié d'entités en commençant par le début. de la collection.

Exemple utilisant first et skip

Lien vers cette section

Interrogez 10 entités Token, décalées de 10 places depuis le début de la collection :

{
tokens(first: 10, skip: 10) {
id
owner
}
}

Exemple utilisant first et id_ge

Lien vers cette section

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.

  • You can use the where parameter in your queries to filter for different properties.
  • You can filter on multiple values within the where parameter.

Exemple utilisant where

Lien vers cette section

Afficher les défis (Challenges) avec résultat failed (échec) :

{
challenges(where: { outcome: "failed" }) {
challenger
outcome
application {
id
}
}
}

Vous pouvez utiliser des suffixes comme _gt, _lte pour comparer les valeurs :

Exemple de filtrage de plage

Lien vers cette section
{
applications(where: { deposit_gt: "10000000000" }) {
id
whitelisted
deposit
}
}

Exemple de filtrage par bloc

Lien vers cette section

You can also filter entities that were updated in or after a specified block with _change_block(number_gte: Int).

Cela peut être utile si vous cherchez à récupérer uniquement les entités qui ont changé, par exemple depuis la dernière fois que vous avez interrogé. Ou bien, il peut être utile d'étudier ou de déboguer la façon dont les entités changent dans votre subgraph (si combiné avec un filtre de bloc, vous pouvez isoler uniquement les entités qui ont changé dans un bloc spécifique).

{
applications(where: { _change_block: { number_gte: 100 } }) {
id
whitelisted
deposit
}
}

Exemple de filtrage d'entités imbriquées

Lien vers cette section

Un filtrage sur la base d'entités imbriquées est possible dans les champs portant le suffixe _.

Cela peut être utile si vous souhaitez récupérer uniquement les entités dont les entités au niveau enfant remplissent les conditions fournies.

{
challenges(where: { application_: { id: 1 } }) {
challenger
outcome
application {
id
}
}
}

Opérateurs logiques

Lien vers cette section

Depuis Graph Node v0.30.0, vous pouvez regrouper plusieurs paramètres dans le même argument where en utilisant les opérateurs et ou ou pour filtrer les résultats en fonction de plusieurs critères.

Opérateur AND
Lien vers cette section

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

Sucre syntaxique : Vous pouvez simplifier la requête ci-dessus en supprimant l'opérateur et en passant une sous-expression séparée par des virgules.

{
challenges(where: { number_gte: 100, outcome: "succeeded" }) {
challenger
outcome
application {
id
}
}
}
Opérateur OR
Lien vers cette section

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

Remarque : lors de la création de requêtes, il est important de prendre en compte l'impact sur les performances de l'utilisation de l'opérateur ou. Bien que ou puisse être un outil utile pour élargir les résultats de recherche, il peut également avoir des coûts importants. L'un des principaux problèmes avec ou est qu'il peut ralentir les requêtes. En effet, ou nécessite que la base de données parcoure plusieurs index, ce qui peut prendre du temps. Pour éviter ces problèmes, il est recommandé aux développeurs d'utiliser les opérateurs et à la place de ou chaque fois que cela est possible. Cela permet un filtrage plus précis et peut conduire à des requêtes plus rapides et plus précises.

Tous les filtres

Lien vers cette section

Liste complète des suffixes de paramètres :

_
_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

Veuillez noter que certains suffixes ne sont pris en charge que pour des types spécifiques. Par exemple, Boolean ne prend en charge que _not, _in et _not_in, mais _ est disponible uniquement pour les types d’objet et d’interface.

En outre, les filtres globaux suivants sont disponibles dans le cadre de l'argument where :

_change_block(numéro_gte : Int)

Interrogation des états précédents

Lien vers cette section

Vous pouvez interroger l'état de vos entités non seulement pour le dernier bloc, qui est la valeur par défaut, mais également pour un bloc arbitraire du passé. Le bloc dans lequel une requête doit se produire peut être spécifié soit par son numéro de bloc, soit par son hachage de bloc en incluant un argument block dans les champs de niveau supérieur des requêtes.

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.

{
challenges(block: { number: 8000000 }) {
challenger
outcome
application {
id
}
}
}

Cette requête renverra les entités Challenge et les entités Application qui leur sont associées, telles qu'elles existaient directement après le traitement du bloc numéro 8 000 000.

{
challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {
challenger
outcome
application {
id
}
}
}

Cette requête renverra les entités Challenge et leurs entités Application associées, telles qu'elles existaient directement après le traitement du bloc avec le hachage donné.

Requêtes de recherche en texte intégral

Lien vers cette section

Les champs de requête de recherche en texte intégral fournissent une API de recherche textuelle expressive qui peut être ajoutée au schéma du subgraph et personnalisée. Reportez-vous à Définition des champs de recherche en texte intégral pour ajouter la recherche en texte intégral à votre subgraph.

Les champs de requête de recherche en texte intégral, fournissent une Api de recherche de texte expressive qui peut être ajoutée au schéma de soubgraph et personnalisée. Reportez-vous à Définition des champs de recherche en texte intégral pour ajouter une recherche en texte intégral à votre subgraph.

Opérateurs de recherche en texte intégral :

SymboleOpérateurDescription
&AndPour combiner plusieurs termes de recherche dans un filtre pour les entités incluant tous les termes fournis
|OrLes requêtes comportant plusieurs termes de recherche séparés par l'opérateur ou renverront toutes les entités correspondant à l'un des termes fournis
<>Follow bySpécifiez la distance entre deux mots.
:*PrefixUtilisez le terme de recherche de préfixe pour trouver les mots dont le préfixe correspond (2 caractères requis.)

En utilisant l'opérateur ou, cette requête filtrera les entités de blog ayant des variations de "anarchism" ou "crumpet" dans leurs champs de texte intégral.

{
blogSearch(text: "anarchism | crumpets") {
id
title
body
author
}
}

L'opérateur follow by spécifie un mot à une distance spécifique dans les documents en texte intégral. La requête suivante renverra tous les blogs contenant des variations de "décentraliser" suivies de "philosophie"

{
blogSearch(text: "decentralized <-> philosophy") {
id
title
body
author
}
}

Combinez des opérateurs de texte intégral pour créer des filtres plus complexes. Avec un opérateur de recherche de prétexte combiné à un suivi de cet exemple, la requête fera correspondre toutes les entités de blog avec des mots commençant par « lou » suivi de « musique ».

{
blogSearch(text: "lou:* <-> music") {
id
title
body
author
}
}

Graph Node met en œuvre une validation basée sur les spécifications des requêtes GraphQL qu'il reçoit à l'aide de graphql-tools-rs, qui est basée sur l'implémentation de référence graphql-js. Les requêtes qui échouent à une règle de validation sont accompagnées d'une erreur standard - consultez la Spécification GraphQL pour en savoir plus.

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 Langauge (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.

Tous les types GraphQL avec des directives @entity dans votre schéma seront traités comme des entités et doivent avoir un champ ID.

Note: Actuellement, tous les types de votre schéma doivent avoir une directive @entity. À l'avenir, nous traiterons les types sans directive @entity comme des objets de valeur, mais cela n'est pas encore possible.

Métadonnées du Subgraph

Lien vers cette section

Tous les subgraphs ont un objet _Meta_ auto-généré, qui permet d'accéder aux métadonnées du subgraph. Cet objet peut être interrogé comme suit :

{
_meta(block: { number: 123987 }) {
block {
number
hash
timestamp
}
deployment
hasIndexingErrors
}
}

Si un bloc est fourni, les métadonnées sont celles de ce bloc, sinon le dernier bloc indexé est utilisé. S'il est fourni, le bloc doit être postérieur au bloc de départ du subgraph et inférieur ou égal au bloc indexé le plus récent.

deployment est un identifiant unique, correspondant au CID IPFS du fichier subgraph.yaml.

block fournit des informations sur le dernier bloc (en tenant compte des contraintes de bloc transmises à _meta) :

  • hash : le hash du bloc
  • number: the block number
  • timestamp : l'horodatage du bloc, si disponible (ceci n'est actuellement disponible que pour les subgraphs indexant les réseaux EVM)

hasIndexingErrors est un booléen identifiant si le subgraph a rencontré des erreurs d'indexation au cours d'un bloc passé

Modifier une page

Précédente
Systèmes distribués
Suivante
Identifiant du Subgraph VS. Identifiant de déploiement
Modifier une page