前言
在传统的 RESTful API 中,客户端需要通过多个接口来获取不同的数据。而在 GraphQL 中,客户端可以通过一个 API 查询出所有需要的数据。这种方式不仅提高了客户端的效率,还可以减少服务器的负担。本文将介绍 GraphQL 的基本概念和使用方法,并且通过一个实际的案例来演示如何构建可扩展的 GraphQL API。
GraphQL 的基本概念
Schema
在 GraphQL 中,Schema 是定义 API 的核心部分。它描述了所有可以查询的对象和它们之间的关系。Schema 由类型、字段和关系组成。
// javascriptcn.com 代码示例 type User { id: ID! name: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! } type Query { user(id: ID!): User post(id: ID!): Post }
这个 Schema 定义了两种类型:User 和 Post。User 包含 id、name、email 和 posts 字段,而 Post 包含 id、title、content 和 author 字段。还定义了两个查询:user 和 post。每个查询都有一个 id 参数,并返回对应的 User 或 Post 对象。
Query
Query 是 GraphQL 中用于获取数据的一种类型。它类似于 RESTful API 中的 GET 请求。一个 Query 可以返回一个或多个对象。
// javascriptcn.com 代码示例 query { user(id: "1") { id name email posts { id title } } }
这个 Query 请求了一个 User 对象,它的 id 为 1。返回的数据包括 id、name、email 和 posts 字段。其中,posts 字段是一个数组,包含了该用户发布的所有 Post 对象的 id 和 title。
Mutation
Mutation 是 GraphQL 中用于修改数据的一种类型。它类似于 RESTful API 中的 POST、PUT 和 DELETE 请求。一个 Mutation 可以返回一个或多个对象。
// javascriptcn.com 代码示例 mutation { createPost(title: "Hello World", content: "This is my first post.") { id title content author { id name } } }
这个 Mutation 创建了一个新的 Post 对象,它包含了 title 和 content 字段。返回的数据包括 id、title、content 和 author 字段。其中,author 字段是一个 User 对象,包含了该 Post 的作者的 id 和 name。
GraphQL 的使用方法
客户端
在客户端中,我们可以使用 GraphQL 的客户端库来发送 Query 和 Mutation 请求。比如,我们可以使用 Apollo Client:
// javascriptcn.com 代码示例 import { ApolloClient, InMemoryCache, gql } from '@apollo/client'; const client = new ApolloClient({ uri: 'https://api.example.com/graphql', cache: new InMemoryCache(), }); client.query({ query: gql` query { user(id: "1") { id name email posts { id title } } } `, }).then(result => console.log(result));
这个客户端发送了一个 Query 请求,它请求了一个 User 对象,它的 id 为 1。返回的数据包括 id、name、email 和 posts 字段。其中,posts 字段是一个数组,包含了该用户发布的所有 Post 对象的 id 和 title。
服务器
在服务器中,我们需要使用 GraphQL 的服务器库来处理 Query 和 Mutation 请求。比如,我们可以使用 Apollo Server:
// javascriptcn.com 代码示例 const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type User { id: ID! name: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! } type Query { user(id: ID!): User post(id: ID!): Post } type Mutation { createPost(title: String!, content: String!): Post! } `; const resolvers = { Query: { user: (parent, { id }, context, info) => { // 查询 User 对象 }, post: (parent, { id }, context, info) => { // 查询 Post 对象 }, }, Mutation: { createPost: (parent, { title, content }, context, info) => { // 创建 Post 对象 }, }, User: { posts: (parent, args, context, info) => { // 查询该用户发布的 Post 对象 }, }, Post: { author: (parent, args, context, info) => { // 查询该 Post 的作者 User 对象 }, }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
这个服务器处理了一个 Query 请求和一个 Mutation 请求。其中,Query 请求处理了 user 和 post 两个查询,Mutation 请求处理了 createPost 一个修改。每个查询和 Mutation 都有一个 resolver 函数来处理它们。还定义了 User 和 Post 对象的 resolver 函数,以处理它们之间的关系。
GraphQL 的实战案例
在本节中,我们将通过一个实际的案例来演示如何构建可扩展的 GraphQL API。我们将使用 Node.js 和 MongoDB 来实现这个案例。
环境设置
首先,我们需要安装一些必要的依赖:
npm install express graphql apollo-server-express mongoose dotenv
然后,我们需要创建一个 .env
文件来存储环境变量:
MONGODB_URI=mongodb://localhost:27017/myapp
数据库模型
我们将创建两个数据库模型:User 和 Post。它们之间有一个一对多的关系。
// javascriptcn.com 代码示例 const mongoose = require('mongoose'); const postSchema = new mongoose.Schema({ title: { type: String, required: true, }, content: { type: String, required: true, }, author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true, }, }); const userSchema = new mongoose.Schema({ name: { type: String, required: true, }, email: { type: String, required: true, unique: true, }, password: { type: String, required: true, }, posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post', }], }); const Post = mongoose.model('Post', postSchema); const User = mongoose.model('User', userSchema); module.exports = { Post, User };
这个模型定义了两个 Schema:Post 和 User。Post 包含 title、content 和 author 字段。其中,author 字段是一个 User 对象的引用。User 包含 name、email、password 和 posts 字段。其中,posts 字段是一个 Post 对象的数组。
数据库连接
我们需要在服务器启动时连接 MongoDB 数据库:
// javascriptcn.com 代码示例 const mongoose = require('mongoose'); const dotenv = require('dotenv'); dotenv.config(); mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true, }).then(() => { console.log('Connected to MongoDB'); }).catch(error => { console.error(error); });
这个代码使用 mongoose.connect
方法来连接 MongoDB 数据库。它从 .env
文件中读取 MONGODB_URI 环境变量。
Resolver 函数
我们需要编写 resolver 函数来处理 Query 和 Mutation 请求。这里,我们将定义一个 resolvers
对象来存储所有的 resolver 函数。
// javascriptcn.com 代码示例 const { User, Post } = require('./models'); const resolvers = { Query: { user: (parent, { id }, context, info) => { return User.findById(id).populate('posts'); }, post: (parent, { id }, context, info) => { return Post.findById(id).populate('author'); }, posts: (parent, args, context, info) => { return Post.find().populate('author'); }, }, Mutation: { createUser: (parent, { name, email, password }, context, info) => { const user = new User({ name, email, password }); return user.save(); }, createPost: async (parent, { title, content, authorId }, context, info) => { const post = new Post({ title, content, author: authorId }); await post.save(); const user = await User.findById(authorId); user.posts.push(post); await user.save(); return post.populate('author'); }, }, User: { posts: (parent, args, context, info) => { return Post.find({ author: parent.id }); }, }, Post: { author: (parent, args, context, info) => { return User.findById(parent.author); }, }, }; module.exports = resolvers;
这个 resolvers
对象定义了四个 Query:user、post、posts 和 createUser。其中,user 和 post 查询返回一个 User 或 Post 对象,posts 查询返回所有 Post 对象的数组,createUser 查询创建一个新的 User 对象。
还定义了一个 Mutation:createPost。它创建一个新的 Post 对象,并将它添加到对应的 User 对象的 posts 数组中。返回的数据包括 id、title、content 和 author 字段。
最后,还定义了 User 和 Post 对象的 resolver 函数,以处理它们之间的关系。
GraphQL API
我们需要使用 Apollo Server 来创建 GraphQL API:
// javascriptcn.com 代码示例 const { ApolloServer } = require('apollo-server-express'); const express = require('express'); const cors = require('cors'); const dotenv = require('dotenv'); const typeDefs = require('./schema'); const resolvers = require('./resolvers'); dotenv.config(); const app = express(); app.use(cors()); const server = new ApolloServer({ typeDefs, resolvers, }); server.applyMiddleware({ app }); app.listen({ port: process.env.PORT || 4000 }, () => { console.log(`Server ready at http://localhost:${process.env.PORT || 4000}${server.graphqlPath}`); });
这个代码创建了一个 Express 应用程序,并使用 Apollo Server 将 GraphQL API 添加到应用程序中。它从 .env
文件中读取 PORT 环境变量。
总结
本文介绍了 GraphQL 的基本概念和使用方法,并通过一个实际的案例来演示如何构建可扩展的 GraphQL API。了解了这些内容之后,你可以使用 GraphQL 来构建更高效、更灵活的 API。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65618e6fd2f5e1655db9a066