GraphQL - 查询

GraphQL 操作可以是读取操作,也可以是写入操作。GraphQL 查询用于读取或获取值,而变异用于写入或发布值。无论哪种情况,操作都是一个简单的字符串,GraphQL 服务器可以解析并以特定格式的数据对其进行响应。通常用于移动和 Web 应用程序的流行响应格式是 JSON。

定义查询的语法如下 −

//语法 1
query query_name{ someField }

//语法 2
{ someField }

以下是查询的示例 −

//带有名称 myQuery 的查询
query myQuery{
    Greeting
}

// 没有任何名称的查询
{
   greeting
}

从上面的例子中可以清楚地看出,查询关键字是可选的。

GraphQL 查询有助于减少过度获取数据。与 Restful API 不同,GraphQL 允许用户限制应从服务器获取的字段。这意味着更小的查询和更少的网络流量;从而减少了响应时间。

图 1 - 使用自定义字段查询学生模型

在此示例中,我们有一组存储在 json 文件中的学生。每个学生模型都有 firstName、lastName 和 id 等字段,但没有 fullName。在这里,我们将讨论如何进行查询以检索所有学生的 fullName。为此,我们需要在两个架构解析器中创建 fullName 字段。

让我们看看如何使用以下步骤 − 来完成此说明

步骤 1 −下载并安装项目所需的依赖项

创建一个名为 query-app 的文件夹。从终端将目录更改为 query-app。稍后,按照环境设置章节中说明的步骤 3 到 5 进行操作。

第 2 步 − 创建架构

在项目文件夹 query-app 中添加 schema.graphql 文件并添加以下代码 −

type Query {
   greeting:String
   students:[Student]
   studentById(id:ID!):Student
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   fullName:String 
}

请注意,students.json 文件中没有 fullName 字段。但是,我们需要通过查询获取学生的 fullname。在这种情况下,fullName 将是一个数据源不可用的自定义字段。

步骤 3 − 创建解析器

在项目文件夹中创建文件 resolvers.js 并添加以下代码 −

const db = require('./db')
const Query = {
    //greeting 的解析器函数
    greeting:() => {
        return "hello from TutorialsPoint !!!"
    },
    
    //students 的解析器函数返回列表
    students:() => db.students.list(),
    
    //studentbyId 的解析器函数
    studentById:(root,args,context,info) => {
      //args 将包含查询中传递的参数
      return db.students.get(args.id);
   }
}

//对于返回的每个 Student 对象,都会调用解析器

const Student = {
   fullName:(root,args,context,info) => {
      return root.firstName+":"+root.lastName
   }
}

module.exports = {Query,Student}

第 4 步 − 运行应用程序

创建一个 server.js 文件。请参阅环境设置章节中的第 8 步。在终端中执行命令 npm start 。服务器将在 9000 端口上启动并运行。在这里,我们使用 GraphiQL 作为客户端来测试应用程序。

打开浏览器并输入 URL http://localhost:9000/graphiql。在编辑器中输入以下查询 −

{
   students{
      id
      fullName
   }
}

查询的响应如下所示 −

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "fullName": "Mohtashim:Mohammad"
         },
         
         {
            "id": "S1002",
            "fullName": "Kannan:Sudhakaran"
         },
         
         {
            "id": "S1003",
            "fullName": "Kiran:Panigrahi"
         }
      ]
   }
}

创建一个 server.js 并添加以下代码 −

const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');

const db = require('./db');
const port = 9000;
const app = express();

//从架构文件加载类型定义
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})

//加载解析器
const resolvers = require('./resolvers')

//绑定架构和解析器
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})

//启用跨域调用和表单发布
app.use(cors(), bodyParser.json());

//启用路由
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

//注册端口
app.listen(port, () => console.info(`服务器在端口 ${port} 上启动`));

在终端中执行命令 npm start。服务器将在 9000 端口上启动并运行。在这里,我们使用 GraphiQL 作为客户端来测试应用程序。

打开浏览器并输入 URL http://localhost:9000/graphiql。在编辑器中输入以下查询 −

{
   students{
      id
      fullName
   }
}

查询的响应如下所示 −

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "fullName": "Mohtashim:Mohammad"
         },
         {
            "id": "S1002",
            "fullName": "Kannan:Sudhakaran"
         },
         {
            "id": "S1003",
            "fullName": "Kiran:Panigrahi"
         }
      ]
   }
}

图 2 - 嵌套查询

让我们创建一个嵌套查询来获取学生详细信息及其大学详细信息。我们将使用相同的项目文件夹。

步骤 1 − 编辑架构

架构文件已经具有 student 字段。让我们添加一个字段 college 并定义其类型。

type College {
   id:ID!
   name:String
   location:String
   rating:Float
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   fullName:String
   college:College
}

第 2 步 − 修改 resolver.js

我们需要添加一个 college 解析器函数,如下所示。 college 解析器函数将针对返回的每个 student 对象执行。 在这种情况下,解析器的根参数将包含 student

const Student = {
   fullName:(root,args,context,info) => {
      return root.firstName+":"+root.lastName
   },
   college:(root) => {
      return db.colleges.get(root.collegeId);
   }
}
module.exports = {Query,Student}

解析器通过调用 college 集合的 get 方法并传递 collegeId 返回每个学生的 college。我们通过 collegeId 建立了 Student 和 College 之间的关联关系。

步骤 3 − 测试应用程序

打开终端窗口并导航到项目文件夹。输入命令 -npm start。启动浏览器并输入 URL http://localhost:9000/graphiql

在 GraphiQL 窗口中输入以下查询 −

{
   students{
      id
      firstName
      college {
         id
         name
         location
         rating
      }
   }
}

查询的响应如下所示 −

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim",
            "college": {
               "id": "col-102",
               "name": "CUSAT",
               "location": "Kerala",
               "rating": 4.5
            }
         },
         
         {
            "id": "S1002",
            "firstName": "Kannan",
            "college": {
               "id": "col-101",
               "name": "AMU",
               "location": "Uttar Pradesh",
               "rating": 5
            }
         },
         
         {
            "id": "S1003",
            "firstName": "Kiran",
            "college": {
               "id": "col-101",
               "name": "AMU",
               "location": "Uttar Pradesh",
               "rating": 5
            }
         }
      ]
   }
}

什么是查询变量?

如果查询需要传递一些动态值,则使用变量表示这些动态值。因此,客户端应用程序可以重用该查询。

插图

让我们创建一个简单的应用程序来了解查询变量。

步骤 1 − 编辑架构文件

添加一个 sayHello 字段,该字段接受字符串参数并返回字符串。名称值在客户端应用程序中将是动态的。

type Query {
    sayHello(name:String!):String
}

步骤 2 −编辑 resolver.js 文件

添加一个 sayHello 解析器,它接受以下参数 −

sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL 服务器对您说 Hello!!`

步骤 3 − 在 GraphiQL 中声明查询变量

变量用 $ 后跟变量名称声明。例如:$myname_Variable。

声明 $myname_Variable 后,必须将其与命名查询语法一起使用。查询 myQuery 采用字符串值并将其传递给 sayHello,如下所示−

query myQuery($myname_Variable:String!) {
   sayHello(name:$myname_Variable)
}

在 GraphiQL 客户端的查询变量部分将 $myname_Variable 的值设置为 JSON 对象。

{
   "myname_Variable": "Mohtashim"
}

上述代码的输出如下 −

{
   "data": {
      "sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
   }
}
查询变量 GraphiQL

如何将查询变量与枚举结合使用

让我们看看当字段参数为枚举类型时如何使用查询变量。

步骤 1 − 编辑 schema.graphql 文件

enum ColorType {
   RED
   BLUE
   GREEN
}

type Query {
   setFavouriteColor(color:ColorType):String
}

setFavouriteColor 函数以枚举作为输入并返回字符串值。

步骤 2 − 编辑 resolvers.js 文件

解析器函数 setFavouriteColor 接受 rootargs。运行时传递给函数的枚举值可通过 args 参数访问。

setFavouriteColor:(root,args) => {
    return "Your Fav Color is :"+args.color;
}

步骤 3 − 在 GraphiQL 中声明查询变量

查询名为 query_to_setColor,它接受名为 color_variable 且 ColorType 的变量。此变量将传递给方法 setFavouriteColor。

query query_to_setColor($color_variable:ColorType) {
    setFavouriteColor(color:$color_variable)
}

在 GraphiQL 的查询变量部分中,输入以下代码 −

{
   "color_variable":"RED"
}

响应如下所示 −

{
   "data": {
      "setFavouriteColor": "Your Fav Color is: RED"
   }
}
Declaring Query Variable