• GraphQL介绍&使用nestjs构建GraphQL查询服务


    GraphQL介绍&使用nestjs构建GraphQL查询服务(文章底部附demo地址)

    GraphQL一种用为你 API 而生的查询语言。出自于Facebook,GraphQL非常易懂,直接看查询语句就能知道查询出来的数据是什么样的。本质上属于API Layer层,负责前端请求的合并、数据整理等功能。

    查询示例

    使用几个简单的例子看下GraphQL的查询是什么样子的。

    普通查询

    {
      me {
        name
      }
    }
    

    查询出来的数据格式如下:

    {
      "me": {
        "name": "wanghao"
      }
    }
    

    1、返回来的数据是一个json
    2、返回数据格式和查询完全一致

    带参数的嵌套查询

    入参格式:

    {
      user(id: 6) {
        name,
        profilePicture {
          width,
          height,
          url
        }
      }
    }
    

    查询出来的数据如下:

    {
      "me" {
        "name": "wanghao,"
        "profilePicture": {
          "width": 50,
          "height": 50,
          "url": "https://cdn/some.jpg"
        }
      }
    }
    

    当然,profilePicture查询时也可以指定参数:

    {
      me {
        name,
        profilePicture(size: 300) {
          width,
          height,
          url
        }
      }
    }
    

    输出可能如下:

    {
      "me" {
        "name": "wanghao,"
        "profilePicture": {
          "width": 300,
          "height": 300,
          "url": "https://cdn/300.jpg"
        }
      }
    }
    

    指定别名查询

    有时候同一字段我们想要查询两次,但是两次指定的参数不同,比如一个用户有多张头像,我们只想查询其中的2张,可以如下:

    {
      me {
        name,
        littlePic: profilePicture(size: 50) {
          width,
          height,
          url
        },
        bigPic: profilePicture(size: 300) {
          width,
          height,
          url
        }
      }
    }
    

    输出结果如下:

    {
      "me" {
        "name": "wanghao,"
        "littlePic": {
          "width": 50,
          "height": 50,
          "url": "https://cdn/50.jpg"
        },
        "bigPic": {
          "width": 300,
          "height": 300,
          "url": "https://cdn/300.jpg"
        }
      }
    }
    

    更多查询请参考:http://graphql.cn/learn/queries/

    变更

    查询只适用于数据查询,但是往往接口还有部分新增、修改、删除操作,这个时候就需要使用变更(Mutations)。

    想要新增一条数据,简单的变更入参如下:

    mutation($inputComment: CommentInput!) {
      addComment(data: $inputComment)
    }
    
    
    

    其中$inputComment是GraphQL中的变量写法,具体如下:

    {
      "inputComment": {
      	"postId": "5a796104fe9b131a10d9627d",
      	"text": "测试评论部分23232"
    	}
    }
    

    返回数据直接如下:

    {
      "data": {
        "addComment": true
      }
    }
    

    实际请求时的数据格式

    GraphQL请求时不限制get、post请求,如果是get,会自动将请求体放在query中,看下实际请求时入参是什么样子的:

    {
        query: "mutation($inputComment: CommentInput!) {↵  addComment(data: $inputComment)↵}↵↵"
        variables: "{↵  "inputComment": {↵"postId":"5a796104fe9b131a10d9627d",↵"text":"测试评论部分23232"↵}"
    }
    

    可以看出,请求时实际发送的是一串字符串至GraphQL服务器,GraphQL服务器会自动解析该字符串内容。

    GraphQL可视化查询工具

    GraphQL的所有实现基本都有实现该可视化工具,进行简单配置即可查看,express-graphql模块配置如下:

    // GraphqQL server route
    app.use('/graphql', graphqlHTTP(req => ({
      schema,
      pretty: true,         // 配置显示pretty按钮进行代码美化
      graphiql: true,       // 配置开启可视化查询
    })));
    

    dataloader

    N+1查询问题

    # 定义
    type User {
      name: String,
      friends: [User]
    }
    
    #查询
    {
      users {
        name
        friends {
          name
          friends {
            name
          }
        } 
      }
    }
    
    

    GraphQL支持嵌套查询,如果没有dataloader,就会出现严重的N+1查询性能问题。

    Dataloader(官方网址)是由facebook推出,能大幅降低数据库的访问频次,经常在Graphql场景中使用。

    import Sequelize from 'sequelize'
    import DataLoader from 'dataloader'
    
    // 定义表结构
    const sequelize = new Sequelize('test', null, null, {
            dialect: 'sqlite',
        })
    const UserModel = sequelize.define('user', {
        name: Sequelize.STRING
    })
    await sequelize.sync({force: true})
    
    //插入测试数据
    await [
        UserModel.create({name: 'ron'}),
        UserModel.create({name: 'john'}),
    ]
    
    // 初始化DataLoader,传入一个批处理函数
    const userLoader = new DataLoader(keys => UserModel.findAll({where: {name: {$in: keys}}})) 
    
    // 以下2个Load语句会被自动批处理,合并成一次数据库的操作
    await [
        userLoader.load('ron'),
        userLoader.load('john')
    ]
    
    
    Executing (default): SELECT id, name, createdAt, updatedAt FROM users AS user WHERE user.name IN ('ron', 'john’);
    

    DataLoader缓存的典型应用是per-request范围的缓存,不能取代redis等应用级别的缓存。

    使用nestjs构建GraphQL Server服务

    nestjs,官网地址:https://docs.nestjs.com,是一个使用typescript构建nodejs后端应用的框架,类似java中的spring框架:依赖注入、拦截器、过滤器、装饰器模式等等,比较看好。

    使用nestjs搭配GraphQL、typeorm、mysql实现了一个简单的GraphQL查询服务,查询支持单个查询、列表查询、关联查询,变更支持修改、删除操作,具体demo地址: https://github.com/caiya/graphql-nestjs-typeorm

  • 相关阅读:
    Java基础——java中String、StringBuffer、StringBuilder的区别
    Java基础——深入剖析Java中的装箱和拆箱
    Java内存分配全面浅析
    基于Appium的移动端UI自动化测试
    测试比对工具,辅助型QA转型之路
    读懂了腾讯和阿里的区别,就读懂了中国商业的秘密!
    Python中的基础数据类型(List,Tuple,Dict)及其常用用法简析
    阿里妈妈技术质量再度重磅开源:国内首个智能化功能测试开源平台Markov
    卧槽,极客时间今天专栏课程突然免费,啥情况?
    Flask 与 Django 先学哪个呢
  • 原文地址:https://www.cnblogs.com/vipzhou/p/8432489.html
Copyright © 2020-2023  润新知