GraphQL学习笔记

这篇博客详细介绍了GraphQL的学习笔记,包括GraphQL的基本类型、枚举定义、类定义、接口类型、联合类型、成员默认值与方法成员、输入类型、命名空间、查询语法、条件查询、指令、片段以及多态查询。内容涵盖了GraphQL查询语言的关键概念和用法,并解释了服务端方法实现的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GraphQL简介

GraphQL主要是一套针对图状数据查询语言,推荐先读读知乎——什么是 GraphQL?

基本类型

先看看提供的基本类型(标量类型)
GraphQL 自带一组默认标量类型:

  • Int:有符号 32 位整数。
  • Float:有符号双精度浮点值。
  • String:UTF‐8 字符序列。
  • Boolean:true 或者 false。
  • ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。
    自定义基本类型(Date是一个type,需要自行实现)
scalar Date

枚举定义

通过enum关键字定义枚举,如

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

类定义

通过使用type进行类型定义,如

type Character {
 	str: String
}

GraphQL中,成员的表示方式是 成员名称:类型名称

	memberName : typeName

通过在类型名称后加上!,代表该成员不能为空,比如如下定义了一个不能为空的数组成员

type Company{
 	human: [String]!
}

在数组的基类型右边加上!代表数组元素不能为空,如下是一个不能为空的数组,且数组元素不能为空

type Company{
 	human: [String!]!
}

接口类型

通过不使用type而使用interface关键字定义一个接口,type可以去实现接口,这要求其实现其所有成员,所以这里的接口更像一些规则的集合而非属性的抽象(需要具备接口的成员),实现多个接口使用&分隔,如

interface Company{
 	human: [String!]!
}
interface Home{
 	family: [String!]!
}
type YytCompany implements Company & Home{
	human: [String!]!
	host: String!
	family: [String!]!
}

联合类型

使用union关键字创建一个可以指代多种类型的类型,比如如下代码表示创建了一个联合类型Author,其可代表Yyt也可代表Eetal,具体值由运行时接收的对象确定

type Yyt{
	name:String
}
type Eetal{
	host:String
}
union Author = Yyt|Eetal;

成员默认值、方法成员

通过在类型右侧使用 = 加上 value,代表为成员提供默认值。通过在成员名称右侧加上形参列表代表为一个方法成员,格式如成员格式,如,方法形参支持 基本类型、枚举和输入类型

type Yyt{
	name:String = "yyt"
}
type Eetal{
	host:String = "yangyitao.top"
}
union Author = Yyt|Eetal;
type AQuery{
	whois(arg : Int):Author 
}

输入类型

输入类型代表可以作为方法成员参数的复杂类型,如下定义一个输入类型,则可以在方法参数中使用该类型

type Review{
  stars: Int!
  commentary: String
}
input ReviewInput {
  stars: Int!
  commentary: String
}
type AQuery{
	Review(arg : ReviewInput):Review
}

命名空间

通过schema关键字指定某些type为命名空间,如

type Query{
}
type Mutation{
}
schema {
  query: Query
  mutation: Mutation
}

查询

  • 服务端定义
type Query{
}
type Mutation{
}
schema {
  query: Query
  mutation: Mutation
}
type Hello{
	name: String = "hello"
	world: Int = 1
	whois(arg2:String) : String
}
type SubHello{
	Hello(arg1:String):Hello
}
  • 简单查询语句
    查询语句直接使用对象格式的导航格式,同级别字段不需要逗号分隔
    语句如果使用query作为schema,可以省略schema名称
    因为查询结果使用json表示,默认使用查询的成员名称作为键,所以多重查询会造成重复覆盖
    需要通过使用别名来避免,格式是
    别名: 查询语句
    如下代码包含一个不使用别名的查询和一个指定别名的查询
query {
	Hello{
		name
	}
	hello2:Hello{
		name
		world
	}
}
  • 查询结果
{
	"data":{
		"Hello":{
				"name":"hello"
			},
		"hello2":{
				"name":"hello",
				"world":1
			}
	}
}
  • 条件查询语句
    如果有些方法成员,需要传递参数,可以通过如下调用
query {
	SubHello{
		Hello(arg1 : "Hi"){
			whois(arg2 : "Hi")
		}
	}
}

查询结果

{
	"data" : {
		"SubHello":{
			"Hello":{
				"whois" : "这里展示的是solve函数具体实现结果"
			}
		}
	}
}

可以看到,有时层级传递参数是一样的,可以通过在查询语句中定义变量传递,如刚刚的查询可以改为

query  Sample($arg : String  = "yyt"){
	SubHello{
		Hello(arg1: $arg){
			whois(arg2 : $arg)
		}
	}
}
  • 指令
    GraphQL还提供@include和@skip,分别代表当表达式成立才执行对应查询,比如
query Sample($arg : String  = "yyt" , $withName : Boolean = false,$skipWorld : Boolean = true){
	SubHello{
		Hello(arg1: $arg){
			whois(arg2 : $arg)
			name @inclue(if : $withName)
			world @skip(if : $skipWorld)
		}
	}
}

执行结果

{
	"data" : {
		"SubHello":{
			"Hello":{
				"whois" : "这里展示的是solve函数具体实现结果"
			}
		}
	}
}
  • 片段
    通过fragment关键字,可以定义查询片段,则在需要的地方通过
    …片段名
    即可完成引入片段代码
    比如
fragment nameFrag{
  name
}
query {
	Hello{
		...nameFrag
	}
}
  • on关键字
    这里我也不知道叫什么好,官方的文档里没有提交这个的叫法,只说了他怎么用,因为查询具备多态性(可能是接口实现,也可能是聚合类型作为方法成员返回值类型),也就是有些方法返回的结果类型具备多个可能,则可以通过on关键字,指定返回不同类型时,筛选展示不同的字段,比如
{
  search(text: "an") {
    __typename
    ... on Human {
      name
      height
    }
    ... on Droid {
      name
      primaryFunction
    }
    ... on Starship {
      name
      length
    }
  }
}

这是官网的demo,阅读了官网的文档真的是有点糟糕,在表明场景前应该先把定义说明比较好吧?上述demo中意思是,__typename是返回当前结果类型,on Human代表如果返回类型是Human就使用前面的运算符运算后面的右值,否则此句查询无效(没有{name height}这个),没错这个是片段运算,这是一种简写,也叫内联片段,所以也可以使用on定义模板,如刚刚查询可以写为

fragment nameFrag on Hello{
  name
}
query {
	Hello{
		...nameFrag
	}
}

为什么没有写服务端的方法实现

因为GraphQL的服务端实现是多语言版本的,可以理解为,其核心是提供这种查询语句的规范服务端定义好这些图状数据,客户端自己定制查询语句。而这些方法成员一般为在服务端,不同语言下,传入一个resolve函数(也就是方法成员的实现,去完成服务端语言的脚本计算。)比如如下为js版本实现

//导入依赖
var { graphql, buildSchema } = require('graphql');

//定义schema
var schema = buildSchema(`
  type Query {
    hello: String
  }
`);

//定义resolve,也就是图状数据,因为在服务端,可以传递服务端语言的函数作为成员值,取值时执行计算
var root = { hello: () => 'Hello world!' };

//查询hello
graphql(schema, '{ hello }', root).then((response) => {
  console.log(response);
});

更多文章,请搜索公众号歪歪梯Club
更多资料,请搜索公众号编程宝可梦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值