Graphql

GraphQL服务器能够接收GraphQL查询语言格式的请求并以所需的形式返回响应。GraphQL是一种API查询语言,可以发送查询并询问您需要什么并准确获取该数据。在这个示例查询中,我们正在寻找地址、链接的标题和添加它的用户的名称:

query { 
    links{ 
        title
        address,
        user{ 
            name
        }
    }
}

响应:

{
  "data": {
    "links": [
      {
        "title": "our dummy link",
        "address": "https://address.org",
        "user": {
          "name": "admin"
        }
      }
    ]
  }
}

模式驱动的开发

在GraphQL中,API从定义所有类型、查询和突变的模式开始,它可以帮助其他人理解API。所以它就像服务器和客户端之间的合同,每当我们需要向GraphQL API添加新功能时,我们必须重新定义模式文件,然后在代码中实现该部分。为此,GraphQL有其模式定义语言。gqlgen是一个用于构建GraphQL服务器的Go库,它有一个很好的特性,可以根据你的模式定义生成代码。

起步

考虑我们在之前文章中描述的页面模型;它非常简单,所以要真正使用GraphQL,我们需要让它更真实一些。让我们为每个页面添加一系列附件;Go模型现在看起来像这样:

type Attachment struct {
   Name     string    `json:"Name"`
   Date     time.Time `json:"Date"`
   Contents string    `json:"Contents"`
}

type Page struct {
   ID          int           `json:"Id"`
   Text        string        `json:"Text"`
   Tags        []string      `json:"Tags"`
   Due         time.Time     `json:"Due"`
   Attachments []*Attachment `json:"Attachments"`
}

具体来说,我们的服务器存在API许多返回页面列表,假设页面现在有如上所述的附件,附件可能相当大。现在使用GET /tag/获取标签的所有任务可能会返回大量数据,然而客户端可能只需要任务的名称,这并不理想,尤其是当网络连接速度较慢或带宽花费较贵时(想想移动客户端,在手机应用程序中向您显示任务列表)。 这就是REST API过度获取的问题。
为了解决过度获取问题,一种常见的方法是只返回带有GET /tag/的页面ID列表,而不是页面本身。然后,有了这个ID列表,客户端可以对其进行迭代并为每个ID发出 GET /page/请求。但是,这里仍然可能有些过度获取,因为我们可能不希望整个页面带有附件;所以我们可以选择只返回附件名称(或ID),并有另一个API来获取这些。
还有获取不足问题,我们发出一大堆网络请求,一些用于获取页面,一些用于获取页面中的附件,在延迟较高的情况下,就会造成严重问题。

graphql如何解决

显然,我们可以设计一个特定的REST API来为我们提供所需的数据。例如,GET /page-name-and-attachment-name-in-tag/可以返回一个页面名称列表,每个页面名称都有一个附件名称列表。没有过度获取,没有获取不足,并且一些REST API具有像这样的专用API;但问题很明显,这很难扩展;现在假设我想要相同的信息,但不是标签,而是截止日期。那么就必须为截止日期编写一个非常相似的API。很明显,随着API变得越来越复杂,将会有很多重复。
另一种选择是我可以向其提交更复杂的请求。我们称之为查询,该查询将准确表达我想要的数据的哪些部分,有点像SQL语言。
这就是GraphQL所做的,让我们看看GraphQL如何解决这个问题。这是一个可以由客户端发送的GraphQL查询:

query {
  getTasksByTag(tag: "shopping") {
    Text
    Attachments{
      Name
    }
  }
}

它将返回一个页面列表,但对于每个页面,只会返回页面的文本及其所有附件的名称,这正是在一个单一的响应中我们想要的数据。

上一篇:数据库(黑马)


下一篇:【嵌入式硬件】步进电机