You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: website/src/pages/en/subgraphs/querying/best-practices.mdx
+99-89Lines changed: 99 additions & 89 deletions
Original file line number
Diff line number
Diff line change
@@ -2,19 +2,19 @@
2
2
title: Querying Best Practices
3
3
---
4
4
5
-
The Graph provides a decentralized way to query data from blockchains. Its data is exposed through a GraphQL API, making it easier to query with the GraphQL language.
6
-
7
-
Learn the essential GraphQL language rules and best practices to optimize your Subgraph.
5
+
Use The Graph's GraphQL API to query [Subgraph](/subgraphs/developing/subgraphs/) data efficiently. This guide outlines essential GraphQL rules, guides, and best practices to help you write optimized, reliable queries.
8
6
9
7
---
10
8
11
9
## Querying a GraphQL API
12
10
13
11
### The Anatomy of a GraphQL Query
14
12
15
-
Unlike REST API, a GraphQL API is built upon a Schema that defines which queries can be performed.
13
+
> GraphQL queries use the GraphQL language, which is defined in the [GraphQL specification](https://spec.graphql.org/).
14
+
15
+
Unlike REST APIs, GraphQL APIs are built on a schema-driven design that defines which queries can be performed.
16
16
17
-
For example, a query to get a token using the `token` query will look as follows:
17
+
Here's a typical query to fetch a `token`:
18
18
19
19
```graphql
20
20
queryGetToken($id: ID!) {
@@ -25,7 +25,7 @@ query GetToken($id: ID!) {
25
25
}
26
26
```
27
27
28
-
which will return the following predictable JSON response (_when passing the proper `$id` variable value_):
28
+
which will return a predictable JSON response (when passing the proper `$id` variable value):
29
29
30
30
```json
31
31
{
@@ -36,8 +36,6 @@ which will return the following predictable JSON response (_when passing the pro
36
36
}
37
37
```
38
38
39
-
GraphQL queries use the GraphQL language, which is defined upon [a specification](https://spec.graphql.org/).
40
-
41
39
The above `GetToken` query is composed of multiple language parts (replaced below with `[...]` placeholders):
- Each `queryName` must only be used once per operation.
56
-
- Each `field` must be used only once in a selection (we cannot query `id` twice under `token`)
57
-
- Some `field`s or queries (like `tokens`) return complex types that require a selection of sub-field. Not providing a selection when expected (or providing one when not expected - for example, on `id`) will raise an error. To know a field type, please refer to [Graph Explorer](/subgraphs/explorer/).
58
-
- Any variable assigned to an argument must match its type.
59
-
- In a given list of variables, each of them must be unique.
60
-
- All defined variables must be used.
53
+
> Important: Failing to follow these rules will result in an error from The Graph API.
61
54
62
-
> Note: Failing to follow these rules will result in an error from The Graph API.
55
+
1. Each `queryName` must only be used once per operation.
56
+
2. Each `field` must be used only once in a selection (you cannot query `id` twice under `token`).
57
+
3. Complex types require a selection of sub-fields.
58
+
- For example, some `fields' or queries (like `tokens`) return complex types which will require a selection of sub-fields. Not providing a selection when expected or providing one when not expected will raise an error, such as `id`. To know a field type, please refer to [Graph Explorer](/subgraphs/explorer/).
59
+
4. Any variable assigned to an argument must match its type.
60
+
5. Variables must be uniquely defined and used.
63
61
64
-
For a complete list of rules with code examples, check out [GraphQL Validations guide](/resources/migration-guides/graphql-validations-migration-guide/).
62
+
**For a complete list of rules with code examples, check out the [GraphQL Validations guide](/resources/migration-guides/graphql-validations-migration-guide/)**.
65
63
66
-
### Sending a query to a GraphQL API
64
+
### How to Send a Query to a GraphQL API
67
65
68
-
GraphQL is a language and set of conventions that transport over HTTP.
66
+
[GraphQL is a query language](https://graphql.org/learn/) and a set of conventions for APIs, typically used over HTTP to request and send data between clients and servers. This means that you can query a GraphQL API using standard `fetch` (natively or via `@whatwg-node/fetch` or `isomorphic-fetch`).
69
67
70
-
It means that you can query a GraphQL API using standard `fetch` (natively or via `@whatwg-node/fetch` or `isomorphic-fetch`).
71
-
72
-
However, as mentioned in ["Querying from an Application"](/subgraphs/querying/from-an-application/), it's recommended to use `graph-client`, which supports the following unique features:
68
+
However, as recommended in [Querying from an Application](/subgraphs/querying/from-an-application/), it's best to use `graph-client`, which supports the following unique features:
73
69
74
70
- Cross-chain Subgraph Handling: Querying from multiple Subgraphs in a single query
-**Queries can be statically analyzed by tools** (more on this in the following sections)
156
+
-Queries are easier to read, manage, and debug.
157
+
-Variable sanitization is handled by the GraphQL server The GraphQL.
158
+
- Variables can be cached at the serverlevel.
159
+
- Queries can be statically analyzed by tools (see [GraphQL Essential Tools](/subgraphs/querying/best-practices/#graphql-essential-tools-guides)).
162
160
163
-
### How to include fields conditionally in static queries
161
+
### 2. Include Fields Conditionally in Static Queries
164
162
165
-
You might want to include the `owner` field only on a particular condition.
163
+
Including fields in static queries only for a particular condition improves performance and keeps responses lightweight by fetching only the necessary data when it's relevant.
166
164
167
-
For this, you can leverage the `@include(if:...)` directive as follows:
165
+
- The `@include(if:...)` directive tells the query to **include** a specific field only if the given condition is true.
166
+
- The `@skip(if: ...)` directive tells the query to **exclude** a specific field if the given condition is true.
167
+
168
+
Example using `owner` field with `@include(if:...)` directive:
@@ -187,15 +188,11 @@ const result = await execute(query, {
187
188
})
188
189
```
189
190
190
-
> Note: The opposite directive is `@skip(if: ...)`.
191
-
192
-
### Ask for what you want
193
-
194
-
GraphQL became famous for its "Ask for what you want" tagline.
191
+
### 3. Ask Only For What You Want
195
192
196
-
For this reason, there is no way, in GraphQL, to get all available fields without having to list them individually.
193
+
GraphQL is known for its "Ask for what you want” tagline, which is why it requires explicitly listing each field you want. There's no built-in way to fetch all available fields automatically.
197
194
198
-
- When querying GraphQL APIs, always think of querying only the fields that will be actually used.
195
+
- When querying GraphQL APIs, always think of querying only the fields that will actually be used.
199
196
- Make sure queries only fetch as many entities as you actually need. By default, queries will fetch 100 entities in a collection, which is usually much more than what will actually be used, e.g., for display to the user. This applies not just to top-level collections in a query, but even more so to nested collections of entities.
200
197
201
198
For example, in the following query:
@@ -215,9 +212,9 @@ query listTokens {
215
212
216
213
The response could contain 100 transactions for each of the 100 tokens.
217
214
218
-
If the application only needs 10 transactions, the query should explicitly set `first: 10` on the transactions field.
215
+
If the application only needs 10 transactions, the query should explicitly set **`first: 10`** on the transactions field.
219
216
220
-
### Use a single query to request multiple records
217
+
### 4. Use a Single Query to Request Multiple Records
221
218
222
219
By default, Subgraphs have a singular entity for one record. For multiple records, use the plural entities and filter: `where: {id_in:[X,Y,Z]}` or `where: {volume_gt:100000}`
223
220
@@ -249,7 +246,7 @@ query ManyRecords {
249
246
}
250
247
```
251
248
252
-
### Combine multiple queries in a single request
249
+
### 5. Combine Multiple Queries in a Single Request
253
250
254
251
Your application might require querying multiple types of data as follows:
This approach will **improve the overall performance** by reducing the time spent on the network (saves you a round trip to the API) and will provide a **more concise implementation**.
304
+
Sending multiple queries in the same GraphQL request **improves the overall performance** by reducing the time spent on the network (saves you a round trip to the API) and provides a **more concise implementation**.
308
305
309
-
### Leverage GraphQL Fragments
306
+
### 6. Leverage GraphQL Fragments
310
307
311
308
A helpful feature to write GraphQL queries is GraphQL Fragment.
312
309
@@ -335,7 +332,7 @@ Such repeated fields (`id`, `active`, `status`) bring many issues:
335
332
- More extensive queries become harder to read.
336
333
- When using tools that generate TypeScript types based on queries (_more on that in the last section_), `newDelegate` and `oldDelegate` will result in two distinct inline interfaces.
337
334
338
-
A refactored version of the query would be the following:
335
+
An optimized version of the query would be the following:
339
336
340
337
```graphql
341
338
query {
@@ -359,27 +356,27 @@ fragment DelegateItem on Transcoder {
359
356
}
360
357
```
361
358
362
-
Using GraphQL `fragment`will improve readability (especially at scale) and result in better TypeScript types generation.
359
+
Using a GraphQL `fragment`improves readability (especially at scale) and results in better TypeScript types generation.
363
360
364
361
When using the types generation tool, the above query will generate a proper `DelegateItemFragment` type (_see last "Tools" section_).
365
362
366
-
###GraphQL Fragment do's and don'ts
363
+
## GraphQL Fragment Guidelines
367
364
368
-
### Fragment base must be a type
365
+
### Do's and Don'ts for Fragments
369
366
370
-
A Fragment cannot be based on a non-applicable type, in short, **on type not having fields**:
367
+
1. Fragments cannot be based on a non-applicable types (types without fields).
368
+
2.`BigInt` cannot be used as a fragment's base because it's a **scalar** (native "plain" type).
369
+
370
+
Example:
371
371
372
372
```graphql
373
373
fragmentMyFragmentonBigInt {
374
374
# ...
375
375
}
376
376
```
377
377
378
-
`BigInt` is a **scalar** (native "plain" type) that cannot be used as a fragment's base.
379
-
380
-
#### How to spread a Fragment
381
-
382
-
Fragments are defined on specific types and should be used accordingly in queries.
378
+
3. Fragments belong to specific types and must be used with those same types in queries.
379
+
4. Spread only fragments matching the correct type.
383
380
384
381
Example:
385
382
@@ -402,20 +399,23 @@ fragment VoteItem on Vote {
402
399
}
403
400
```
404
401
405
-
`newDelegate` and `oldDelegate` are of type `Transcoder`.
402
+
-`newDelegate` and `oldDelegate` are of type `Transcoder`. It's not possible to spread a fragment of type `Vote` here.
406
403
407
-
It is not possible to spread a fragment of type `Vote` here.
404
+
5. Fragments must be defined based on their specific usage.
405
+
6. Define fragments as an atomic business unit of data.
408
406
409
-
#### Define Fragment as an atomic business unit of data
407
+
---
410
408
411
-
GraphQL `Fragment`s must be defined based on their usage.
409
+
### How to Define `Fragment` as an Atomic Business Unit of Data
412
410
413
-
For most use-case, defining one fragment per type (in the case of repeated fields usage or type generation) is sufficient.
411
+
> For most use-cases, defining one fragment per type (in the case of repeated fields usage or type generation) is enough.
414
412
415
413
Here is a rule of thumb for using fragments:
416
414
417
415
- When fields of the same type are repeated in a query, group them in a `Fragment`.
418
-
- When similar but different fields are repeated, create multiple fragments, for instance:
416
+
- When similar but different fields are repeated, create multiple fragments.
417
+
418
+
Example:
419
419
420
420
```graphql
421
421
# base fragment (mostly used in listing)
@@ -438,47 +438,57 @@ fragment VoteWithPoll on Vote {
438
438
439
439
---
440
440
441
-
## The Essential Tools
441
+
## GraphQL Essential Tools Guides
442
+
443
+
### Test Queries with Graph Explorer
444
+
445
+
Before integrating GraphQL queries into your dapp, it's best to test them. Instead of running them directly in your app, use a web-based playground.
446
+
447
+
Start with [Graph Explorer](https://thegraph.com/explorer), a preconfigured GraphQL playground built specifically for Subgraphs. You can experiment with queries and see the structure of the data returned without writing any frontend code.
448
+
449
+
If you want alternatives to debug/test your queries, check out other similar web-based tools:
450
+
451
+
-[GraphiQL](https://graphiql-online.com/graphiql)
452
+
-[Altair](https://altairgraphql.dev/)
442
453
443
-
### GraphQL web-based explorers
454
+
### Setting up Workflow and IDE Tools
444
455
445
-
Iterating over queries by running them in your application can be cumbersome. For this reason, don't hesitate to use [Graph Explorer](https://thegraph.com/explorer) to test your queries before adding them to your application. Graph Explorer will provide you a preconfigured GraphQL playground to test your queries.
456
+
In order to keep up with querying best practices and syntax rules, use the following workflow and IDE tools.
446
457
447
-
If you are looking for a more flexible way to debug/test your queries, other similar web-based tools are available such as [Altair](https://altairgraphql.dev/) and [GraphiQL](https://graphiql-online.com/graphiql).
458
+
#### GraphQL ESLint
448
459
449
-
### GraphQL Linting
460
+
1. Install GraphQL ESLint
450
461
451
-
In order to keep up with the mentioned above best practices and syntactic rules, it is highly recommended to use the following workflow and IDE tools.
462
+
Use [GraphQL ESLint](https://the-guild.dev/graphql/eslint/docs/getting-started) to enforce best practices and syntax rules with zero effort.
452
463
453
-
**GraphQL ESLint**
464
+
2. Use the ["operations-recommended"](https://the-guild.dev/graphql/eslint/docs/configs) config
454
465
455
-
[GraphQL ESLint](https://the-guild.dev/graphql/eslint/docs/getting-started)will help you stay on top of GraphQL best practices with zero effort.
466
+
This will enforce essential rules such as:
456
467
457
-
[Setup the "operations-recommended"](https://the-guild.dev/graphql/eslint/docs/configs) config will enforce essential rules such as:
468
+
-`@graphql-eslint/fields-on-correct-type`: Ensures fields match the proper type.
469
+
-`@graphql-eslint/no-unused variables`: Flags unused variables in your queries.
458
470
459
-
-`@graphql-eslint/fields-on-correct-type`: is a field used on a proper type?
460
-
-`@graphql-eslint/no-unused variables`: should a given variable stay unused?
461
-
- and more!
471
+
Result: You'll **catch errors without even testing queries** on the playground or running them in production!
462
472
463
-
This will allow you to **catch errors without even testing queries** on the playground or running them in production!
473
+
#### Use IDE plugins
464
474
465
-
### IDE plugins
475
+
GraphQL plugins streamline your workflow by offering real-time feedback while you code. They highlight mistakes, suggest completions, and help you explore your schema faster.
466
476
467
-
**VSCode and GraphQL**
477
+
1. VS Code
468
478
469
-
The [GraphQL VSCode extension](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql)is an excellent addition to your development workflow to get:
479
+
Install the [GraphQL VS Code extension](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql) to unlock:
470
480
471
481
- Syntax highlighting
472
482
- Autocomplete suggestions
473
483
- Validation against schema
474
484
- Snippets
475
485
- Go to definition for fragments and input types
476
486
477
-
If you are using `graphql-eslint`, the [ESLint VSCode extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) is a must-have to visualize errors and warnings inlined in your code correctly.
487
+
If you are using `graphql-eslint`, use the [ESLint VS Code extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) to visualize errors and warnings inlined in your code correctly.
478
488
479
-
**WebStorm/Intellij and GraphQL**
489
+
2.WebStorm/Intellij and GraphQL
480
490
481
-
The [JS GraphQL plugin](https://plugins.jetbrains.com/plugin/8097-graphql/) will significantly improve your experience while working with GraphQL by providing:
491
+
Install the [JS GraphQL plugin](https://plugins.jetbrains.com/plugin/8097-graphql/). It significantly improves the experience of working with GraphQL by providing:
0 commit comments