今日份的学习——GraphQL篇

814 阅读3分钟

今日份的学习——GraphQL

graplql是一个类似于restful的api查询语言,由Facebook开源,今天我们就来学习一下它。

学无止境,谁让我好蔡啊?!

image

想法是做一个关于有以下功能的demo

  • 书列表
  • 书详细信息
  • 新增书
  • 删除书

说干就干

首先搭建后端服务,使用nodejs+express,数据库选择mlab,是一个免费的线上数据库服务,以学习为目的,快捷方便就好。

首先我们搭建一下基础服务,这里的api见官网,不做解释。

没想到吧!

const graphqlHTTP = require('express-graphql');

//定义的数据模板和查询逻辑,见下文
const schema = require('./schema/schema');

app.use(
  //指定api对应的url后缀
  '/graphql',
  graphqlHTTP({
    schema,
    graphiql: true
  })
);

app.listen(4000, () => {
  console.log('now listen on port 4000');
});

在学习graphql的时候,我把它和mongoose作了下类比,mongoose通过new一个Schema作为模板来执行数据库操作,graphql则是通过GraphQLObjectType这个对象来生成一个模板, 具体代码如下:

const BookType = new GraphQLObjectType({
  name: 'Book',
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    genre: { type: GraphQLString },
    author: {
      type: AuthorType,
      resolve(parent, args) {
        return Author.findById(parent.authorId);
      }
    }
  })
});

这里我们生成了一个书的对象

现在我要抓一个人做我对象

fields的类型可为object或()=>object对应了查询的字段,书拥有

id主键、name名称、genre类型、author作者字段

字段的type指定了字段的类型,类似typescript但是此处的都是由graphql引入的,GraphQLID指的是ID可能是stringnumber,这里使用ID会接受这两种参数并自动转化为string类型。eg:

假设id在数据库中是string类型,为"233666"
而传入的是233666,我们希望也可以查到
就可以使用"GraphQLID"
会自动转换为"233666"

graphql支持嵌套查询,并且显而易见author会有很多内容,比如姓名,出过的书籍,所以author的type对应的是author对象(详情见下文),resolve能返回一个值、promise、promise数组,也就是数据库操作的返回值。

AuthorType又是什么?

接着生成一个author的对象,和书类似

const AuthorType = new GraphQLObjectType({
  name: 'Author',
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    age: { type: GraphQLInt },
    books: {
      type: new GraphQLList(BookType),
      resolve(parent, args) {
        // return _.filter(books, { authorId: parent.id });
        return Book.find({ authorId: parent.id });
      }
    }
  })
});

一个作者可能有多本书,所以books字段需要返回一个列表GraphQLList,这里定义了一个BookType类型的列表作为type,resolve同理。

有了书和作者的对象我们就来搭建模板,根据官网api,我们需要这样定义

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    book: {
      type: BookType,
      args: { id: { type: GraphQLID } },
      resolve(parent, args) {
        //从哪里得到数据,比如数据库或其他来源
        //Mongodb mysql postgresql
        return Book.findById(args.id);
      }
    },
    author: {
      type: AuthorType,
      args: { id: { type: GraphQLID } },
      resolve(parent, args) {
        return Author.findById(args.id);
      }
    },
    books: {
      type: new GraphQLList(BookType),
      resolve(parent, args) {
        return Book.find({});
      }
    },
    authors: {
      type: new GraphQLList(AuthorType),
      resolve(parent, args) {
        return Author.find({});
      }
    }
  }
});

module.exports = new GraphQLSchema({
  query: RootQuery,
});

这也就是一开始导入的schema,这里定义了4个查询方法,分别是

  • 根据id查询书
  • 根据id查询作者
  • 查询书列表
  • 查询作者列表

现在我们把这个项目启动一下(这里极力推荐nodemon这个库,可以避免修改代码每次重启), 然后访问 http://localhost:4000/graphql 就会出现一个神奇的亚子

我说,老奶奶你坐稳了,我要开车了(巴啦啦小魔仙游呢娃子)

不对不对,是这个。

图片

现在我们根据灰色文字提示输入一些查询语句

{
  books{
    name
    id
  }
}
//然后点击左上方运行按钮

查询成功

查询成功了,但是这些数据是我手动操作数据库写死的,生产环境这样玩不得被打死?那下节我们学习下如何使用graphql新增修改删除数据。

所有代码都放到了github,如果喜欢,请点个赞。

工头催了,告辞