1. 概述

GraphQL 已被广泛用作Web服务通信模式。其基本理念是为客户端应用程序提供灵活的使用方式。

在这篇教程中,我们将探讨灵活性的另一个方面:如何让GraphQL字段以不同的名称暴露出来。

2. GraphQL架构

让我们以一个具有不同作者的博客为例。GraphQL架构看起来像这样:

query {
    recentPosts(count: 1, offset: 0){
        id
        title
        text
        category
        author {
            id
            name
            thumbnail
        }
    }
}

type Post {
    id: ID!
    title: String!
    text: String!
    category: String
    authorId: Author!
}

type Author {
    id: ID!
    name: String!
    thumbnail: String
    posts: [Post]!
}

我们可以获取最近的帖子。每个post都会附带其author。查询结果如下:

{
    "data": {
        "recentPosts": [
            {
                "id": "Post00",
                "title": "Post 0:0",
                "text": "Post 0 + by author 0",
                "category": null,
                "author": {
                    "id": "Author0",
                    "name": "Author 0",
                    "thumbnail": "http://example.com/authors/0"
                }
            }
        ]
    }
}

3. 以不同的名称暴露GraphQL字段

客户端应用程序可能需要使用first_author字段。目前它正在使用author。为了满足这个需求,我们有两种解决方案:

  • 更新GraphQL服务器的架构定义
  • 利用GraphQL中的别名概念

让我们逐个来看。

3.1. 修改架构

让我们更新post的架构定义:

type Post {
    id: ID!
    title: String!
    text: String!
    category: String
    first_author: Author!
}

author字段并非简单的,它是一个复杂的字段。我们也需要更新处理方法来适应这个变化。

PostController中的@SchemaMapping标记为author(Post post)的方法,需要更改为getFirst_author(Post post)。或者,可以在@SchemaMappingfield属性中添加新的字段名称。

以下是查询示例:

query{
    recentPosts(count: 1,offset: 0){
        id
        title
        text
        category
        first_author{
            id
            name
            thumbnail
        }
    }
}

上述查询的结果如下:

{
    "data": {
        "recentPosts": [
            {
                "id": "Post00",
                "title": "Post 0:0",
                "text": "Post 0 + by author 0",
                "category": null,
                "first_author": {
                    "id": "Author0",
                    "name": "Author 0",
                    "thumbnail": "http://example.com/authors/0"
                }
            }
        ]
    }
}

这种解决方案存在两个主要问题:

  • 它改变了架构和服务器端实现
  • 它强迫其他客户端应用遵循更新后的架构定义

这些问题与GraphQL提供的灵活性特性相矛盾。

3.2. GraphQL别名

在GraphQL中,别名允许我们在不改变架构定义的情况下将字段的结果重命名为任何我们想要的名字。要在查询中引入别名,只需在别名和冒号符号(:)之前放置GraphQL字段。

这里是一个演示查询的例子:

query {
    recentPosts(count: 1,offset: 0) {
        id
        title
        text
        category
        first_author:author {
            id
            name
            thumbnail
        }
    }
}

上述查询的结果如下:

{
    "data": {
        "recentPosts": [
            {
                "id": "Post00",
                "title": "Post 0:0",
                "text": "Post 0 + by author 0",
                "category": null,
                "first_author": {
                    "id": "Author0",
                    "name": "Author 0",
                    "thumbnail": "http://example.com/authors/0"
                }
            }
        ]
    }
}

请注意,查询本身请求的是第一个帖子。其他客户端应用可能会请求first_post而不是recentPosts。这时,别名就能派上用场。

query {
    first_post: recentPosts(count: 1,offset: 0) {
        id
        title
        text
        category
        author {
            id
            name
            thumbnail
        }
    }
}

上述查询的结果如下:

{
    "data": {
        "first_post": [
            {
                "id": "Post00",
                "title": "Post 0:0",
                "text": "Post 0 + by author 0",
                "category": null,
                "author": {
                    "id": "Author0",
                    "name": "Author 0",
                    "thumbnail": "http://example.com/authors/0"
                }
            }
        ]
    }
}

这两个例子清楚地展示了使用GraphQL时的灵活性。每个客户端应用可以根据需要自行更新,而服务器端的架构定义和实现保持不变。

4. 总结

在这篇文章中,我们研究了两种以不同的名称暴露GraphQL字段的方法。我们介绍了别名的概念,并通过示例解释了它是正确的方法。

如往常一样,本文的示例代码可在GitHub上找到。