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