GraphQL API
Reading time: 13 min
Learn about the GraphQL Query API used in The Graph.
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 and .
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.
查询模式中定义的单个 Token
实体:
{token(id: "1") {idowner}}
Note: When querying for a single entity, the id
field is required, and it must be writen as a string.
查询所有 Token
实体:
{tokens {idowner}}
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.
{tokens(orderBy: price, orderDirection: asc) {idowner}}
The following example shows tokens sorted by the name of their owner:
{tokens(orderBy: owner__name, orderDirection: asc) {idowner {name}}}
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.
查询前10 个代币:
{tokens(first: 10) {idowner}}
要查询集合中间的实体组,skip
参数可以与 first
参数结合使用,以跳过集合开头的指定数量实体。
查询从集合开头偏移 10 个位置的 10 个Token
实体:
{tokens(first: 10, skip: 10) {idowner}}
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 }) {idowner}}}
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.
查询包含failed
属性的challenges 的 结果:
{challenges(where: { outcome: "failed" }) {challengeroutcomeapplication {id}}}
您可以使用 _gt
、_lte
等后缀进行值比较:
{applications(where: { deposit_gt: "10000000000" }) {idwhitelisteddeposit}}
You can also filter entities that were updated in or after a specified block with _change_block(number_gte: Int)
.
如果您只想获取已经更改的实体,例如自上次轮询以来改变的实体,那么这将非常有用。或者也可以调查或调试子图中实体的变化情况(如果与区块过滤器结合使用,则只能隔离在特定区块中发生变化的实体)。
{applications(where: { _change_block: { number_gte: 100 } }) {idwhitelisteddeposit}}
可以在带 _
后缀的字段中基于嵌套实体进行筛选。
如果您希望只获取其子级实体满足条件的实体,那么这可能很有用。
{challenges(where: { application_: { id: 1 } }) {challengeroutcomeapplication {id}}}
从Graph 节点 版本开始,您可以在同一where
参数中对多个参数进行分组,使用and``or
运算符根据多个标准筛选结果。
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" }] }) {challengeroutcomeapplication {id}}}
**语法糖:**您可以通过传递一个用逗号分隔的子表达式来删除and
运算符,从而简化上述查询。
{challenges(where: { number_gte: 100, outcome: "succeeded" }) {challengeroutcomeapplication {id}}}
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" }] }) {challengeroutcomeapplication {id}}}
注意:在构造查询时,重要的是要考虑使用or
运算符对性能的影响。虽然or
可能是扩大搜索结果的有用工具,但它也可能有巨大的成本。or
的主要问题之一是它可能会导致查询速度减慢。这是因为or
需要数据库扫描多个索引,这可能是一个耗时的过程。为了避免这些问题,建议开发人员尽可能使用和运算符而不是或。这允许更精确地过滤,并可以导致更快、更准确的查询。
参数后缀的完整列表:
__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
请注意,某些后缀仅支持特定类型。 例如,Boolean
仅支持 _not
、_in
和 _not_in
,但是_
只适用于对象和接口类型。。
此外,以下全局过滤器作为 where
参数的一部分可用:
_change_block(number_gte: Int)
您可以查询实体的状态,不仅查询默认的最新区块,还可以查询过去的任意区块。通过在查询的顶级字段中包含block
参数,可以通过区块号或区块哈希指定应该发生查询的区块。
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. explains what these limitations are in detail.
{challenges(block: { number: 8000000 }) {challengeroutcomeapplication {id}}}
此查询将返回 Challenge
实体及其关联的 Application
实体,因为它们在处理第 8000000 区块后就存在了。
{challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {challengeroutcomeapplication {id}}}
此查询将返回 Challenge
实体及其关联的 Application
实体,因为它们在处理具有给定哈希值的区块后就存在了。
全文搜索查询字段提供了一个表达性的文本搜索 API,可以添加到子图模式中并进行自定义。 请参阅以将全文搜索添加到您的子图中。
全文搜索查询有一个必填字段 text
,用于提供搜索词。 在这个 text
搜索字段中可以使用几个特殊的全文运算符。
全文搜索运算符:
符号 | 运算符 | 描述 |
---|---|---|
& | And | 用于将多个搜索词组合到包含所有提供词条的实体的过滤器中 |
| | Or | 由 or 运算符分隔的多个搜索词的查询,将返回与任何提供的词匹配的所有实体 |
<-> | Follow by | 指定两个单词之间的距离。 |
:* | Prefix | 使用前缀搜索词查找前缀匹配的单词(需要 2 个字符) |
使用 or
运算符,此查询将过滤到在其全文字段中具有“anarchism”或“crumpet”变体的 blog 实体。
{blogSearch(text: "anarchism | crumpets") {idtitlebodyauthor}}
follow by
运算符指定全文文档中相隔特定距离的单词。 以下查询将返回所有“decentralize”后跟着“philosophy”变体的日志。
{blogSearch(text: "decentralized <-> philosophy") {idtitlebodyauthor}}
可以将全文运算符进行组合来制作更复杂的过滤器。 在下面的查询示例中,使用前缀搜索运算符与其他运算符的结合,可以实现匹配所有以“lou”开头后,跟着“music”单词的日志实体。
{blogSearch(text: "lou:* <-> music") {idtitlebodyauthor}}
Graph Node使用对其接收的GraphQL查询进行的验证,该工具基于。验证规则失败的查询会出现标准错误-请访问了解更多信息。
The schema of your dataSources, i.e. the entity types, values, and relationships that are available to query, are defined through the .
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 .
Note: Our API does not expose mutations because developers are expected to issue transactions directly against the underlying blockchain from their applications.
模式定义中所有带有 @entity
指示的 GraphQL 类型都将被视为实体,并且必须具有 ID
字段。
注意: 目前,模式定义中的所有类型都必须具有 @entity
指示。 将来,我们会将没有 @entity
指示的类型视为值对象,但目前尚不支持。
所有子图都有一个自动生成的_Meta_
对象,它提供对子图元数据的访问。可按如下方式查询:
{_meta(block: { number: 123987 }) {block {numberhashtimestamp}deploymenthasIndexingErrors}}
如果提供了区块,则元数据为该区块的元数据,如果未使用最新的索引区块。如果提供,则区块必须在子图的起始区块之后,并且小于或等于最近索引的区块。
deployment
是一个唯一的ID,对应于subgraph.yaml
文件的IPFS CID。
block
提供有关最新区块的信息(考虑传递给_meta
的任何区块约束):
- hash:区块的哈希
- number:区块编号
- timestamp:区块的时间戳(如果可用)(当前仅适用于索引EVM网络的子图)
hasIndexingErrors
是一个布尔值,用于标识子图在过去的某个区块中是否遇到索引错误。