前言
GraphQL 是一种用于 API 设计的查询语言和运行时。Hapi 是一个 Node.js 的 web 框架,具有高度的可扩展性和定制性。结合使用 Hapi 和 GraphQL 可以构建出高效、可靠的 API 服务。
本文将介绍如何在 Hapi 框架中使用 GraphQL,包括安装和配置,以及 GraphQL 的基本语法和实践案例。文章旨在提供深度的学习和指导意义。
安装和配置
在开始之前,首先需要安装 Hapi 和相关的插件。具体步骤如下:
安装 Hapi
npm install hapi
安装 GraphQL 协议插件
npm install hapi-graphql
安装 GraphQL 解析器插件
npm install graphql
GraphQL 的基本语法
GraphQL 有三种类型的操作:查询、变异和订阅。我们将重点介绍查询操作,其中最基本的查询语句如下:
{ FIELD_NAME }
其中,FIELD_NAME 是你要查询的字段名。如果需要传入参数,则可以在 FIELD_NAME 后跟上参数列表,例如:
{ USER(id: "123") { name email } }
上述代码将查询 id 为 123 的用户的名字和邮箱地址。
如果需要查询多个字段,则可以使用花括号包含多个子查询:
{ USER(id: "123") { name email } POSTS(author: "123") { title content } }
上述代码将查询 id 为 123 的用户的名字和邮箱,以及作者 id 为 123 的所有文章的标题和内容。
实践案例
下面是一个基于 Hapi 和 GraphQL 的实践案例。假设我们要构建一个简单的图书管理系统,包括书籍、作者和出版商三个实体。我们需要能够查询书籍、作者和出版商的信息,以及根据不同条件获取它们的列表。
数据模型
首先,我们需要定义数据模型。我们可以使用 MongoDB 或其他数据库管理系统存储数据。下面是一个简单的 MongoDB Schema 定义:
const mongoose = require('mongoose'); const BookSchema = mongoose.Schema({ title: String, author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' }, publisher: { type: mongoose.Schema.Types.ObjectId, ref: 'Publisher' } }); const AuthorSchema = mongoose.Schema({ name: String, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }] }); const PublisherSchema = mongoose.Schema({ name: String, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }] }); const BookModel = mongoose.model('Book', BookSchema); const AuthorModel = mongoose.model('Author', AuthorSchema); const PublisherModel = mongoose.model('Publisher', PublisherSchema); module.exports = { BookModel, AuthorModel, PublisherModel };
GraphQL Schema
然后,我们可以使用 GraphQL 构建数据查询模式。下面是一个简单的查询模式定义:
const { GraphQLObjectType, GraphQLSchema, GraphQLList, GraphQLID, GraphQLString } = require('graphql'); const { BookModel, AuthorModel, PublisherModel } = require('./models'); const BookType = new GraphQLObjectType({ name: 'Book', fields: { id: { type: GraphQLID }, title: { type: GraphQLString }, author: { type: AuthorType, async resolve(parent, args) { return await AuthorModel.findById(parent.author); } }, publisher: { type: PublisherType, async resolve(parent, args) { return await PublisherModel.findById(parent.publisher); } } } }); const AuthorType = new GraphQLObjectType({ name: 'Author', fields: { id: { type: GraphQLID }, name: { type: GraphQLString }, books: { type: new GraphQLList(BookType), async resolve(parent, args) { return await BookModel.find({ author: parent.id }); } } } }); const PublisherType = new GraphQLObjectType({ name: 'Publisher', fields: { id: { type: GraphQLID }, name: { type: GraphQLString }, books: { type: new GraphQLList(BookType), async resolve(parent, args) { return await BookModel.find({ publisher: parent.id }); } } } }); const RootQuery = new GraphQLObjectType({ name: 'RootQueryType', fields: { books: { type: new GraphQLList(BookType), args: { id: { type: GraphQLID }, title: { type: GraphQLString }, author: { type: GraphQLID }, publisher: { type: GraphQLID } }, async resolve(parent, args) { const query = {}; if (args.id) { query._id = args.id; } if (args.title) { query.title = args.title; } if (args.author) { query.author = args.author; } if (args.publisher) { query.publisher = args.publisher; } return await BookModel.find(query); } }, authors: { type: new GraphQLList(AuthorType), args: { id: { type: GraphQLID }, name: { type: GraphQLString } }, async resolve(parent, args) { const query = {}; if (args.id) { query._id = args.id; } if (args.name) { query.name = args.name; } return await AuthorModel.find(query); } }, publishers: { type: new GraphQLList(PublisherType), args: { id: { type: GraphQLID }, name: { type: GraphQLString } }, async resolve(parent, args) { const query = {}; if (args.id) { query._id = args.id; } if (args.name) { query.name = args.name; } return await PublisherModel.find(query); } } } }); const schema = new GraphQLSchema({ query: RootQuery }); module.exports = schema;
上述代码定义了三种类型:BookType、AuthorType 和 PublisherType,并通过 RootQuery 将它们关联起来。在 RootQuery 中,我们还定义了三个查询调用 books、authors 和 publishers 来获取列表。
Hapi Server
最后,我们将 GraphQL Schema 和 Hapi Server 整合在一起。下面是一个简单的 Hapi 服务器实现:
const Hapi = require('hapi'); const { graphqlHapi } = require('hapi-graphql'); const { connect } = require('mongoose'); const schema = require('./schema'); const server = new Hapi.Server({ host: 'localhost', port: 8000 }); connect('mongodb://localhost/books', { useNewUrlParser: true }) .then(() => { console.log('Connected to DB'); }) .catch(error => { console.log(error); }); server.register({ plugin: graphqlHapi, options: { path: '/graphql', graphqlOptions: { schema }, route: { cors: true } } }); server.route({ method: 'GET', path: '/', handler: async (request, h) => { return 'Welcome to GraphQL Server'; } }); server.start(error => { if (error) { console.log(error); } console.log(`Server started at: ${server.info.uri}`); });
在上述代码中,我们首先使用 Mongoose 连接 MongoDB,然后注册 graphqlHapi 插件,将 GraphQL Schema 和 Hapi Server 集成在一起。最后,我们定义一个根路由,以确保服务器运行正常。
总结
本文介绍了如何在 Hapi 框架中使用 GraphQL,包括安装和配置,以及 GraphQL 的基本语法和实践案例。GraphQL 是一种灵活的查询语言和运行时,结合 Hapi 可以构建高效、可靠的 API 服务,提供了更加灵活的数据查询和处理能力。希望本文对你有所帮助,如果有任何问题或意见,请随时留言。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6590b298eb4cecbf2d5ff881