查询 > GraphQL API

GraphQL API

Reading time: 14 min

This guide explains the GraphQL Query API that is used for The Graph Protocol.

查询

链到本节

在您的子图模式中,定义了称为 Entities 的类型。 对于每个 Entity 类型,将在顶级 Query 类型上生成一个 entityentities 字段。 请注意,使用Graph 时,query 不需要包含在 graphql 查询的顶部。

例子

链到本节

查询模式中定义的单个 Token 实体:

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

**注意:**查询单个实体时,id字段为必填项,而且必须为字符串。

查询所有 Token 实体:

{
tokens {
id
owner
}
}

排序

链到本节

查询集合时,orderBy 参数可用于按特定属性排序。 此外,orderDirection 可用于指定排序方向,asc 用于升序,而desc 用于降序。

示例

链到本节
{
tokens(orderBy: price, orderDirection: asc) {
id
owner
}
}

嵌套实体筛选示例

链到本节

从Graph 节点 v0.30.0开始,可以根据嵌套实体对实体进行排序。

在以下示例中,我们根据代币所有者的名称对其进行排序:

{
tokens(orderBy: owner__name, orderDirection: asc) {
id
owner {
name
}
}
}

目前,您可以在@entity@derivedFrom字段上按一级深度的StringID类型进行排序。不幸的是,目前还不支持按一级深层实体上的接口排序、按数组和嵌套实体的字段排序。

分页

链到本节

查询集合时,可以使用 first 参数从集合的开头进行分页。 值得注意的是,默认排序顺序是按 ID 以字母数字升序排列,而不是按创建时间排列。

此外,skip 参数可用于跳过实体和分页。 例如 first:100 显示前 100 个实体,first:100, skip:100 显示接下来的 100 个实体。

查询应该避免使用非常大的 skip 值,因为它们通常性能表现不佳。 要检索大量项目,最好根据上一个示例中所示的属性对实体进行分页。

使用first的示例

链到本节

查询前10 个代币:

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

要查询集合中间的实体组,skip 参数可以与 first 参数结合使用,以跳过集合开头的指定数量实体。

使用firstskip的示例

链到本节

查询从集合开头偏移 10 个位置的 10 个Token 实体:

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

使用firstid_ge的示例

链到本节

如果客户端需要检索大量实体,则基于属性进行查询和过滤会明显提高性能。 例如,客户端可以使用以下查询检索大量代币:

query manyTokens($lastID: String) { tokens(first: 1000, where: { id_gt: $lastID }) {
id
owner
}
}
}

第一次,它会发送带有 lastID = "" 的查询,对于后续请求,会将 lastID 设置为上一个请求中的最后一个实体的id 属性。 与简单的提高 skip 值相比,这种方法的性能要好得多。

过滤

链到本节

您可以在查询中使用 where 参数来过滤不同的属性。 您可以在 where 参数内过滤多个值。

使用where的示例

链到本节

查询包含failed 属性的challenges 的 结果:

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

您可以使用 _gt_lte 等后缀进行值比较:

范围过滤示例

链到本节
{
applications(where: { deposit_gt: "10000000000" }) {
id
whitelisted
deposit
}
}

区块过滤示例

链到本节

您还可以通过 _ change _ block (number _ gte: Int)过滤实体-这个过滤器在指定的区块中或之后更新的实体。

如果您只想获取已经更改的实体,例如自上次轮询以来改变的实体,那么这将非常有用。或者也可以调查或调试子图中实体的变化情况(如果与区块过滤器结合使用,则只能隔离在特定区块中发生变化的实体)。

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

嵌套实体筛选示例

链到本节

可以在带 _ 后缀的字段中基于嵌套实体进行筛选。

如果您希望只获取其子级实体满足条件的实体,那么这可能很有用。

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

逻辑运算符

链到本节

从Graph 节点 v0.30.0版本开始,您可以在同一where参数中对多个参数进行分组,使用and``or运算符根据多个标准筛选结果。

AND运算符
链到本节

在下面的示例中,我们正在筛选outcome``succeedednumber大于或等于100的挑战。

{
challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {
challenger
outcome
application {
id
}
}
}

**语法糖:**您可以通过传递一个用逗号分隔的子表达式来删除and运算符,从而简化上述查询。

{
challenges(where: { number_gte: 100, outcome: "succeeded" }) {
challenger
outcome
application {
id
}
}
}
OR运算符
链到本节

在下面的示例中,我们正在筛选outcome``succeedednumber大于或等于100的挑战。

{
challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {
challenger
outcome
application {
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参数,可以通过区块号或区块哈希指定应该发生查询的区块。

这种查询结果不会随着时间的推移而改变,即对过去某个区块的查询,无论何时执行,都将返回相同的结果。唯一的例外是,如果您在非常靠近链头的区块上进行查询,如果该区块不在主链上,并且链被重新组织,则结果可能会改变。 一旦一个区块被确认是最终的区块,那么查询的结果就不会改变。

请注意,当前的实现仍然受到某些限制,这些限制可能会违反这些保证。该实现不能总是判断给定的区块哈希根本不在主链上,或者对于一个不能被认为是最终的区块,逐块哈希查询的结果可能会受到与查询同时运行的区块重组的影响。当区块是最终区块并且已知在主链上时,它们不会影响区块哈希查询的结果。这个问题详细解释了这些限制是什么。

示例

链到本节
{
challenges(block: { number: 8000000 }) {
challenger
outcome
application {
id
}
}
}

此查询将返回 Challenge 实体及其关联的 Application 实体,因为它们在处理第 8000000 区块后就存在了。

示例

链到本节
{
challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {
challenger
outcome
application {
id
}
}
}

此查询将返回 Challenge 实体及其关联的 Application 实体,因为它们在处理具有给定哈希值的区块后就存在了。

全文搜索查询

链到本节

全文搜索查询字段提供了一个表达性的文本搜索 API,可以添加到子图模式中并进行自定义。 请参阅定义全文搜索字段以将全文搜索添加到您的子图中。

全文搜索查询有一个必填字段 text,用于提供搜索词。 在这个 text 搜索字段中可以使用几个特殊的全文运算符。

全文搜索运算符:

符号运算符描述
&And用于将多个搜索词组合到包含所有提供词条的实体的过滤器中
|Or由 or 运算符分隔的多个搜索词的查询,将返回与任何提供的词匹配的所有实体
<->Follow by指定两个单词之间的距离。
:*Prefix使用前缀搜索词查找前缀匹配的单词(需要 2 个字符)

例子

链到本节

使用 or 运算符,此查询将过滤到在其全文字段中具有“anarchism”或“crumpet”变体的 blog 实体。

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

follow by 运算符指定全文文档中相隔特定距离的单词。 以下查询将返回所有“decentralize”后跟着“philosophy”变体的日志。

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

可以将全文运算符进行组合来制作更复杂的过滤器。 在下面的查询示例中,使用前缀搜索运算符与其他运算符的结合,可以实现匹配所有以“lou”开头后,跟着“music”单词的日志实体。

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

验证

链到本节

Graph Node使用graphql-tools-rs对其接收的GraphQL查询进行基于规范的验证,该工具基于GraphQL-js引用实现。验证规则失败的查询会出现标准错误-请访问GraphQL规范了解更多信息。

模式

链到本节

数据源的模式,即可用于查询的实体类型、值和关系,是通过GraphQL接口定义语言(IDL)定义的。

GraphQL模式通常定义查询订阅突变的根类型。Graph仅支持查询。子图的根查询类型是从子图清单中包含的GraphQL模式自动生成的。

**注意:**我们的 API 不提供对变种的支持,因为开发人员会从他们的应用程序中直接针对底层区块链发出交易。

实体

链到本节

模式定义中所有带有 @entity 指示的 GraphQL 类型都将被视为实体,并且必须具有 ID 字段。

注意: 目前,模式定义中的所有类型都必须具有 @entity 指示。 将来,我们会将没有 @entity 指示的类型视为值对象,但目前尚不支持。

子图元数据

链到本节

所有子图都有一个自动生成的_Meta_对象,它提供对子图元数据的访问。可按如下方式查询:

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

如果提供了区块,则元数据为该区块的元数据,如果未使用最新的索引区块。如果提供,则区块必须在子图的起始区块之后,并且小于或等于最近索引的区块。

deployment是一个唯一的ID,对应于subgraph.yaml文件的IPFS CID。

block提供有关最新区块的信息(考虑传递给_meta的任何区块约束):

  • hash:区块的哈希
  • number:区块编号
  • timestamp:区块的时间戳(如果可用)(当前仅适用于索引EVM网络的子图)

hasIndexingErrors是一个布尔值,用于标识子图在过去的某个区块中是否遇到索引错误。

编辑

上页
分布式系统
下页
Subgraph ID vs Deployment ID
编辑