如今,大多数应用程序都需要从服务器获取数据,而这些数据都存储在数据库中。GraphQL 是一种新的 API 标准,它为 REST 提供了一种更高效、更强大、更灵活的替代方案。它允许客户端只从服务器获取所需的数据。 GraphQL 经常被混淆为一种数据库技术,但这是一种误解,GraphQL 是一种 API 查询语言,而不是数据库。从这个意义上说,它与数据库无关,可以有效地用于任何使用 API 的环境。
graphql-yoga
是一款功能齐全的 GraphQL 服务器,注重易用性、性能和良好的开发人员体验。此外,它还支持 Apollo 等所有 GraphQL 客户端。
现在,您已经了解了 GraphQL 是什么,可以学习在 Nodejs 应用程序中使用它来代替 REST。
创建新项目
新建一个名为 UsersAPI 的文件夹,打开终端并导航到该文件夹,然后运行以下命令:
1npm init
在项目文件夹中创建名为 index.js
的文件:
1touch index.js
这就完成了应用程序的设置。
安装所需的依赖项
您需要安装 graphql-yoga
来帮助设置 GraphQL 服务器,然后安装 mongoose
来帮助连接 Mongo 数据库。
在终端中运行以下程序:
1npm install graphql-yoga mongoose
定义用户模型
模型负责从底层 MongoDB 数据库中创建和读取文档。在此,我们将为 GraphQL 应用程序创建一个用户模型。
在 index.js
中键入以下代码:
1const { GraphQLServer } = require('graphql-yoga')
2const mongoose = require('mongoose');
3mongoose.connect("mongodb://localhost:27017/UserApp");
4
5const User= mongoose.model("User",{
6 fullname: String,
7 username: String,
8 phone_number: String,
9 city: String
10});
我们已经成功定义了用户模型并建立了 mongoose 连接,现在是时候进入 GraphQL 模式了。
定义 GraphQL 模式
GraphQL 模式描述了连接到该模式的客户端可用的功能。它使用模式定义语言构建。
在您的 index.js
文件中添加以下代码行:
1const typeDefs = `type Query {
2 getUser(id: ID!): User
3 getUsers: [User]
4 }
5 type User {
6 id: ID!
7 fullname: String!
8 username: String!
9 phone_number: String!
10 city: String!
11 }
12 type Mutation {
13 addUser(fullname: String!, username: String!, phone_number: String!, city: String!): User!,
14 deleteUser(id: ID!): String
15 }`
我们的模式中有三种类型,让我们对它们进行细分。
使用查询类型
GraphQL 查询用于获取数据,与基于 REST 的应用程序接口中的 GET 动词类似。 为了定义服务器上可以进行哪些查询,在模式定义语言(Schema Definition Language)中使用了查询类型。查询类型是一种根级类型,它为客户端定义了功能,并充当模式中其他更具体类型的入口点。
1type Query {
2 getUser(id: ID): User
3 getUsers: [User]
4}
在此查询类型中,我们定义了两种可在 GraphQL 服务器上使用的查询类型: getUser:返回与所提供 ID 匹配的特定用户对象。 getUsers:返回一个用户对象列表。
如果您熟悉基于 REST 的应用程序接口,通常会发现这些应用程序接口位于不同的端点上,但 GraphQL 允许同时对它们进行查询,并一次性返回结果。
注意:方括号表示您希望在 JSON 响应中得到一个可迭代对象或数组。您只会为 getUser 返回一个用户对象,为 getUsers 返回一个数组。
使用用户类型
用户是一种 GraphQL 对象类型,这意味着它是一种包含某些字段的类型。对象类型是模式中最常用的类型,代表一组字段。
1type User {
2 id: ID!
3 fullname: String!
4 username: String!
5 phone_number: String!
6 city: String!
7}
id、全名、用户名、电话号码和城市是用户类型的_____________________________________字段。
String 是内置标量类型之一。它指定了字段的数据类型。 String 表示字段不可为空。在模式定义语言中,我们用感叹号来表示。 ID 是唯一标识符,通常用作缓存的键。
使用突变类型
突变被发送到服务器以创建、更新或删除数据,这与 RESTful API 上的 PUT、POST、PATCH 和 DELETE 动词类似。 就像查询类型定义了 GraphQL 服务器上数据获取操作的入口点一样,根级突变类型也指定了数据操作的入口点。
1type Mutation {
2 addUser(fullname: String!, username: String!, phone_number: String!, city: String!): User!,
3 deleteUser(id: ID!): String
4}
这实现了两个突变:
addUser
: 接受全名、用户名、电话号码和城市作为参数,称为 "输入类型",突变将返回新创建的用户对象。deleteUser
: 接受一个有效的用户 ID,并返回一个字符串信息,说明删除操作是否成功。
让我们继续为我们定义的模式编写解析器。
添加解析器
解析器是在 GraphQL API 中对数据执行业务逻辑的实际函数。每个查询和突变都有相应的解析器函数来执行逻辑。
在您的 index.js
文件中添加以下代码行:
1const resolvers = {
2 Query: {
3 getUsers: ()=> User.find(),
4 getUser: async (_,{id}) => {
5 var result = await User.findById(id);
6 return result;
7 }
8},
9 Mutation: {
10 addUser: async (_, { fullname, username, phone_number, city }) => {
11 const user = new User({fullname, username, phone_number, city});
12 await user.save();
13 return user;
14 },
15 deleteUser: async (_, {id}) => {
16 await User.findByIdAndRemove(id);
17 return "User deleted";
18 }
19 }
20 }
设置 GraphQL 服务器
构建模式和解析器之后,就该设置服务器来处理请求了。graphql-yoga "是启动和运行 GraphQL 服务器的最简单方法,它是一个功能齐全的 GraphQL 服务器,注重用户友好的配置、性能和良好的开发人员体验。
在 index.js
中,添加以下代码行以设置服务器:
1const server = new GraphQLServer({ typeDefs, resolvers })
2mongoose.connection.once("open", function(){
3 server.start(() => console.log('Server is running on localhost:4000'))
4});
这样,你就从零开始构建了一个功能强大的 GraphQL 服务器,现在是提出一些请求的时候了。打开终端,运行以下命令启动服务器:
1node index.js
打开网络浏览器并导航至 http://localhost:4000/,浏览器上就会出现一个漂亮的 GraphQL 游戏场地,您可以在此运行示例查询。
添加新用户
在 playground 中运行以下查询,添加一个新用户:
1mutation{
2 addUser(fullname:"Ibe Ogele",username:"ibesoft",phone_number:"2348102331921",city:"Enugu"){
3 id
4 fullname
5 username
6 phone_number
7 city
8 }
9}
获取用户信息
运行下面的查询,获取某个用户的信息:
1query{
2 getUser(id:"user_id"){
3 id
4 fullname
5 username
6 phone_number
7 city
8 }
9}
让所有用户运行:
1query{
2 getUsers{
3 id
4 fullname
5 username
6 phone_number
7 city
8 }
9}
删除用户
您可以通过运行下面的查询删除某个用户:
1mutation{
2 deleteUser(id: "user_id")
3}
结论
使用 GraphQL,您可以向您的应用程序接口发送查询,并准确获得您所需的信息,不多也不少。GraphQL 查询总是返回可预测的结果。