什么是graphQL

文章目录

  • 一、入门
      • 1.是什么?做什么
      • 2.如何做?
  • 二、查询和变更
      • 1.字段(Fields)
      • 2.参数(Arguments)
      • 3.别名(Aliases)
      • 4.片段(Fragments)
      • 5.操作名称(Operation name)
      • 6.变量(Variables)
      • 7.变量定义(Variable definitions)
      • 8.默认变量(Default variables)
      • 9.指令(Directives)
      • 10.变更(Mutations)
        • 变更中的多个字段(Multiple fields in mutations)

一、入门

1.是什么?做什么

  • GraphQL是一种语言(用于查询API)
  • 使用基于类型系统来执行查询的服务端运行时(类型系统由你决定)

2.如何做?

一旦一个 GraphQL 服务运行起来(通常在 web 服务的一个 URL 上),它就能接收 GraphQL 查询,并验证和执行。接收到的查询首先会被检查确保它只引用了已定义的类型和字段,然后运行指定的解析函数来生成结果。

例如这个查询:

{me {name}
}

会产生这样的JSON结果:

{"me": {"name": "Luke Skywalker"}
}

二、查询和变更

1.字段(Fields)

GraphQL 是关于请求对象上的特定字段。我们以一个非常简单的查询以及其结果为例:

//*字段指代string*
{hero {name}
}
{"data": {"hero": {//《星球大战》主角的名字是:"R2-D2""name": "R2-D2"}}
}

你立即就能发现,查询和其结果拥有几乎一样的结构。这是 GraphQL 最重要的特性,因为这样一来,你就总是能得到你想要的数据,而服务器也准确地知道客户端请求的字段。

在上一个例子中,我们请求了我们主角的名字,返回了一个字符串类型(String),但是字段也能指代对象类型(Object)

这个时候,你可以对这个对象的字段进行次级选择(sub-selection)。GraphQL 查询能够遍历相关对象及其字段,使得客户端可以一次请求查询大量相关数据,而不像传统 REST 架构中那样需要多次往返查询。

{hero {name# 查询可以有备注!friends {name}}
}
{"data": {"hero": {"name": "R2-D2","friends": [{"name": "Luke Skywalker"},{"name": "Han Solo"},{"name": "Leia Organa"}]}}
}

注意这个例子中,friends 返回了一个数组的项目,GraphQL 查询会同等看待单个项目或者一个列表的项目,然而我们可以通过 schema 所指示的内容来预测将会得到哪一种。

2.参数(Arguments)

即使GraphQL仅做到了遍历对象及其字段,它就已经是一个非常有用的数据查询语言了。但是当你加入给字段传递参数的能力时,事情会变得更加有趣。

{human(id: "1000") {nameheight}
}
{"data": {"human": {"name": "Luke Skywalker","height": 1.72}}
}

在类似 REST 的系统中,你只能传递一组简单参数 —— 请求中的 query 参数和 URL 段。但是在 GraphQL 中,每一个字段和嵌套对象都能有自己的一组参数,从而使得 GraphQL 可以完美替代多次 API 获取请求。甚至你也可以给 标量(scalar)字段传递参数,用于实现服务端的一次转换,而不用每个客户端分别转换。

{human(id: "1000") {nameheight(unit: FOOT)}
}
{"data": {"human": {"name": "Luke Skywalker","height": 5.6430448}}
}

参数可以是多种不同的类型。上面例子中,我们使用了一个枚举类型,其代表了一个有限选项集合(本例中为长度单位,即是 METER 或者 FOOT)。GraphQL 自带一套默认类型,但是 GraphQL 服务器可以声明一套自己的定制类型,只要能序列化成你的传输格式即可。

3.别名(Aliases)

如果你眼睛够锐利,你可能已经发现,即便结果中的字段与查询中的字段能够匹配,但是因为他们并不包含参数,你就没法通过不同参数来查询相同字段。这便是为何你需要别名 —— 这可以让你重命名结果中的字段为任意你想到的名字。

{empireHero: hero(episode: EMPIRE) {name}jediHero: hero(episode: JEDI) {name}
}
{"data": {"empireHero": {"name": "Luke Skywalker"},"jediHero": {"name": "R2-D2"}}
}

上例中,两个 hero 字段将会存在冲突,但是因为我们可以将其另取一个别名,我们也就可以在一次请求中得到两个结果。

4.片段(Fragments)

假设我们的 app 有比较复杂的页面,将正反派主角及其友军分为两拨。你立马就能想到对应的查询会变得复杂,因为我们需要将一些字段重复至少一次 —— 两方各一次以作比较。

这就是为何 GraphQL 包含了称作片段的可复用单元。片段使你能够组织一组字段,然后在需要它们的地方引入。下面例子展示了如何使用片段解决上述场景:

{leftComparison: hero(episode: EMPIRE) {...comparisonFields}rightComparison: hero(episode: JEDI) {...comparisonFields}
}fragment comparisonFields on Character {nameappearsInfriends {name}
}
{"data": {"leftComparison": {"name": "Luke Skywalker","appearsIn": ["NEWHOPE","EMPIRE","JEDI"],"friends": [{"name": "Han Solo"},{"name": "Leia Organa"},{"name": "C-3PO"},{"name": "R2-D2"}]},"rightComparison": {"name": "R2-D2","appearsIn": ["NEWHOPE","EMPIRE","JEDI"],"friends": [{"name": "Luke Skywalker"},{"name": "Han Solo"},{"name": "Leia Organa"}]}}
}

你可以看到上面的查询如何漂亮地重复了字段。片段的概念经常用于将复杂的应用数据需求分割成小块,特别是你要将大量不同片段的 UI 组件组合成一个初始数据获取的时候。

5.操作名称(Operation name)

这之前,我们都使用了简写句法,省略了 query 关键字和查询名称,但是生产中使用这些可以使我们代码减少歧义。

下面的示例包含了作为操作类型的关键字 query 以及操作名称 HeroNameAndFriends

query HeroNameAndFriends {hero {namefriends {name}}
}
{"data": {"hero": {"name": "R2-D2","friends": [{"name": "Luke Skywalker"},{"name": "Han Solo"},{"name": "Leia Organa"}]}}
}

操作类型可以是 querymutationsubscription,描述你打算做什么类型的操作。操作类型是必需的,除非你使用查询简写语法,在这种情况下,你无法为操作提供名称或变量定义。

操作名称是你的操作的有意义和明确的名称。它仅在有多个操作的文档中是必需的,但我们鼓励使用它,因为它对于调试和服务器端日志记录非常有用。 当在你的网络或是 GraphQL 服务器的日志中出现问题时,通过名称来从你的代码库中找到一个查询比尝试去破译内容更加容易。 就把它想成你喜欢的程序语言中的函数名。例如,在 JavaScript 中,我们只用匿名函数就可以工作,但是当我们给了函数名之后,就更加容易追踪、调试我们的代码,并在其被调用的时候做日志。同理,GraphQL 的查询和变更名称,以及片段名称,都可以成为服务端侧用来识别不同 GraphQL 请求的有效调试工具。

6.变量(Variables)

目前为止,我们将参数写在了查询字符串内。但是在很多应用中,字段的参数可能是动态的:例如,可能是一个"下拉菜单"让你选择感兴趣的《星球大战》续集,或者是一个搜索区,或者是一组过滤器。

*将这些动态参数直接传进查询字符串并不是好主意,因为这样我们的客户端就得动态地在运行时操作这些查询字符串了,再把它序列化成 GraphQL 专用的格式。*其实,GraphQL 拥有一级方法将动态值提取到查询之外,然后作为分离的字典传进去。这些动态值即称为变量

使用变量之前,我们得做三件事:

  1. 使用 $variableName 替代查询中的静态值。
  2. 声明 $variableName 为查询接受的变量之一。
  3. variableName: value 通过传输专用(通常是 JSON)的分离的变量字典中。

全部做完之后就像这个样子:

# { "graphiql": true, "variables": { "episode": JEDI } }
query HeroNameAndFriends($episode: Episode) {hero(episode: $episode) {namefriends {name}}
}

这样一来,我们的客户端代码就只需要传入不同的变量,而不用构建一个全新的查询了。这事实上也是一个良好实践,意味着查询的参数将是动态的 —— 我们决不能使用用户提供的值来字符串插值以构建查询。

7.变量定义(Variable definitions)

变量定义看上去像是上述查询中的 ($episode: Episode)。其工作方式跟类型语言中函数的参数定义一样。它以列出所有变量,变量前缀必须为 $,后跟其类型,本例中为 Episode

所有声明的变量都必须是标量、枚举型或者输入对象类型。所以如果想要传递一个复杂对象到一个字段上,你必须知道服务器上其匹配的类型。可以从Schema页面了解更多关于输入对象类型的信息。

变量定义可以是可选的或者必要的。上例中,Episode 后并没有 !,因此其是可选的。但是如果你传递变量的字段要求非空参数,那变量一定是必要的。

如果想要进一步了解变量定义的句法,可以学习 GraphQL 的 schema 语言。schema 语言在 Schema 中有细述。

8.默认变量(Default variables)

可以通过在查询中的类型定义后面附带默认值的方式,将默认值赋给变量。

query HeroNameAndFriends($episode: Episode = "JEDI") {hero(episode: $episode) {namefriends {name}}
}

当所有变量都有默认值的时候,你可以不传变量直接调用查询。如果任何变量作为变量字典的部分传递了,它将覆盖其默认值。

9.指令(Directives)

我们上面讨论的变量使得我们可以避免手动字符串插值构建动态查询。传递变量给参数解决了一大堆这样的问题,但是我们可能也需要一个方式使用变量动态地改变我们查询的结构。譬如我们假设有个 UI 组件,其有概括视图和详情视图,后者比前者拥有更多的字段。

我们来构建一个这种组件的查询:

query Hero($episode: Episode, $withFriends: Boolean!) {hero(episode: $episode) {namefriends @include(if: $withFriends) {name}}
}
{"episode": "JEDI","withFriends": false
}
//"withFriends": false
{"data": {"hero": {"name": "R2-D2"}}
}
//"withFriends": false
{"data": {"hero": {"name": "R2-D2","friends": [{"name": "Luke Skywalker"},{"name": "Han Solo"},{"name": "Leia Organa"}]}}
}

我们用了 GraphQL 中一种称作指令的新特性。一个指令可以附着在字段或者片段包含的字段上,然后以任何服务端期待的方式来改变查询的执行。GraphQL 的核心规范包含两个指令,其必须被任何规范兼容的 GraphQL 服务器实现所支持:

  • @include(if: Boolean) 仅在参数为 true 时,包含此字段。
  • @skip(if: Boolean) 如果参数为 true,跳过此字段。

指令在你不得不通过字符串操作来增减查询的字段时解救你。服务端实现也可以定义新的指令来添加新的特性。

10.变更(Mutations)

GraphQL 的大部分讨论集中在数据获取,但是任何完整的数据平台也都需要一个改变服务端数据的方法。

REST 中,任何请求都可能最后导致一些服务端副作用,但是约定上建议不要使用 GET 请求来修改数据。GraphQL 也是类似 —— 技术上而言,任何查询都可以被实现为导致数据写入。然而,建一个约定来规范任何导致写入的操作都应该显式通过变更(mutation)来发送。

就如同查询一样,如果任何变更字段返回一个对象类型,你也能请求其嵌套字段。获取一个对象变更后的新状态也是十分有用的。我们来看看一个变更例子:

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {createReview(episode: $ep, review: $review) {starscommentary}
}
{"ep": "JEDI","review": {"stars": 5,"commentary": "This is a great movie!"}
}
{"data": {"createReview": {"stars": 5,"commentary": "This is a great movie!"}}
}

注意 createReview 字段如何返回了新建的 review 的 starscommentary 字段。这在变更已有数据时特别有用,例如,当一个字段自增的时候,我们可以在一个请求中变更并查询这个字段的新值。

你也可能注意到,这个例子中,我们传递的 review 变量并非标量。它是一个输入对象类型,一种特殊的对象类型,可以作为参数传递。你可以在 Schema 页面上了解到更多关于输入类型的信息。

变更中的多个字段(Multiple fields in mutations)

一个变更也能包含多个字段,一如查询。查询和变更之间名称之外的一个重要区别是:

查询字段时,是并行执行,而变更字段时,是线性执行,一个接着一个。

这意味着如果我们一个请求中发送了两个 incrementCredits 变更,第一个保证在第二个之前执行,以确保我们不会出现竞态。

mutation UpdateUserAndCreatePost {updateUser(id: 1, input: {name: "新名称", email: "new.email@example.com"}) {idnameemail} createPost(input: {title: "新股票标题", content: "我买了新的股票!"}) {idtitlecontent}
}

上面示例中,updateUser优先于createPost执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你知道数据是如何为制造业精益生产KPI和供应链管理赋能的吗?

挖掘工业数据价值,形成新质生产力 随着工业4.0的逐步深入和国家对制造业高质量发展的大力扶持,工业数据的重要性愈发凸显,已然成为生产经营活动中不可或缺的核心要素。 工业数据不仅反映了生产流程中的各个环节,更蕴含了丰富的信…

嵌入式单片机的高级编程技巧和优化

引言 嵌入式单片机(MCU)是实现智能设备控制的核心,广泛应用于工业自动化、智能家居、医疗设备等领域。 下面将探讨STM32单片机的高级编程技巧,包括中断管理、低功耗模式和内存优化等方面,并提供具有一定难度的代码示…

深度学习的炼金术:转化数据为黄金的秘密

深度学习的炼金术:转化数据为黄金的秘密 1 引言 在现代深度学习的壮阔疆域中,数据是王冠上耀眼的宝石,而性能优化则是锻造这顶王冠的炼金术。这份融合了数据和算法魔力的艺术,不仅仅依赖于强大的计算资源和复杂的网络结构&#x…

【蓝桥杯省赛真题40】python摘苹果 中小学青少年组蓝桥杯比赛 算法思维python编程省赛真题解析

目录 python摘苹果 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python摘苹果 第十三届蓝桥杯青少年组python编程省赛真题 一、题目要求 &…

【C语言】万字详讲操作符

目录 前言 一、操作符分类 二、算数操作符 三、移位操作符 四、位操作符 五、赋值操作符 六、单目操作符 6.1 逻辑反操作 6.2 负值与正值 6.3 取地址 6.4 sizeof 6.5 取反操作符 6.6 --和操作符 6.7 间接访问操作符(解引用操作符) 6.8 强…

QA | amfori QMI 审核常见问题解答

01amfori QMI 项目介绍 作为全球领先的贸易协会,amfori 致力于开放和可持续贸易。他们汇集了来自 40 多个国家的零售商、进口商、品牌和协会,目的是系统地监督和改善世界各地的供应商的工作条件。 amfori QMI 是一项针对致力于为生产现场的作业规范和质量…

level2行情+在线金融数据库

jvQuant:一站式金融量化服务平台 jvQuant作为一个领先的金融量化服务平台,为广大投资者和量化分析师提供了全面、高效、稳定的数据接入和量化分析服务。该平台涵盖了多个关键功能,包括交易接入、WebSocket行情接入、历史行情查询、在线数据库…

安装JAVA和java IDEA并汉化过程

1.安装java: 打开java的下载链接: Java Downloads | Oracle 然后选择对应的版本下载即可,我这里是windows 所以下载这个 然后正常一步步安装即可。 2.配置java环境: 在桌面右键此电脑然后点击属性——高级系统设置——环境变量——然后…

H5点击复制功能 兼容安卓、IOS

效果图 HTML代码 <div>链接&#xff1a;<span style"color: #FF8A21" click"CopyUrl" id"copyId"> https://blog.csdn.net/qq_51463650?spm1000.2115.3001.5343</span> </div>复制方法 const CopyUrl () > {let …

12.Blender 界面介绍(上)及物体基础编辑操作

设置语言 首先在菜单栏打开编辑-Preferences-界面-翻译&#xff0c;可以修改语言 这里使用的是Steam上下载的4.1版本 工具栏 左边的工具栏&#xff0c;按T就会出现&#xff0c;再按T就会隐藏 右边的工具栏是按N&#xff0c;按N显示&#xff0c;再按N隐藏 旋转画面 长按鼠…

微信小程序监听App中的globalData——全局数据监听

微信小程序监听App中的globalData——全局数据监听 定义数据定义监听方法注册监听方法修改监听的数据扩展 需求&#xff1a;微信小程序项目需要全局监听某个数据。 方法&#xff1a;在 app.ts/app.js 中定义 globalData 公共数据&#xff0c;然后定义一个监听方法 watch&…

CSS 标准流 浮动 Flex布局

目录 1. 标准流2. 浮动2.1 清除浮动 3. Flex 布局3.1 Flex 组成3.2 Flex 布局 - 主轴与侧轴对齐方式3.2.1 主轴对齐方式3.2.2 侧轴对齐方式 3.3 Flex 布局 - 修改主轴方向3.4 Flex 布局 - 弹性伸缩比3.5 Flex 布局 - 弹性盒子换行3.6 Flex 布局 - 行对齐方式 1. 标准流 标准流…

使用selenium时出现element click intercepted报错的解决办法

win10&#xff0c;python3.8.10。 selenium版本如下&#xff08;用pip38 show selenium查看&#xff09;&#xff1a; 在定位中&#xff0c;定位了一个按钮&#xff08;特点&#xff1a;button下还有span然后才是文本&#xff09;&#xff0c;代码如下&#xff1a; from sele…

ubuntu22.04 CH340/CH34x 驱动安装

CH34x驱动地址&#xff1a;CH341SER_LINUX.ZIP - 南京沁恒微电子股份有限公司 1、卸载旧驱动&#xff08;如果存在&#xff09; sudo rmmod ch341.ko 2、解压进入 driver 目录 unzip CH341SER_LINUX.ZIP cd CH341SER_LINUX/driver 3、编译 make 可能错误&#xff1a; make[1]…

51单片机中断和定时的结合应用

#include <reg52.h>unsigned int cnt 0;sbit led P1^1;// 初始化定时器 void TimerSetup(){TMOD 0x01; // 定时器的第1个模式TH0 0xB8; // 定时器的初始值-高位TL0 0x00; // 定时器的初始值-低位TR0 1; //启动定时器cnt 0;EA 1; // 开启总中断ET0 1; // 时间中断…

4月26日 阶段性学习汇报

1.毕业设计与毕业论文 毕业设计已经弄完&#xff0c;加入了KNN算法&#xff0c;实现了基于四种常见病的判断&#xff0c;毕业论文写完&#xff0c;格式还需要调整&#xff0c;下周一发给指导老师初稿。目前在弄答辩ppt&#xff08;25%&#xff09;。25号26号两天都在参加校运会…

Python升级打怪(5)

链式调用:用一个函数的返回值作为另外一个函数参数 嵌套调用:一个函数在另一个函数定义里面&#xff0c;而调用该定义函数既可以使用在其里面的函数 在Pycharm中调试器的左下角能够看到函数之间的"调用栈" 调用栈里面描述了当前这个代码的函数之间&#xff0c;调用…

AI生图美学在淘宝的实践应用

本文介绍了如何制定和应用美学标准来评估和改善人工智能生成的图像质量&#xff0c;特别是在电商领域的应用&#xff0c;主要分为制定美学标准、训练美学模型、应用美学模型、升级淘宝风格模型四个步骤。 美学的定义与分析 图像质量标准&#xff1a;现代设计框架下&#xff0c;…

git 分支重命名 使用IDEA进行操作

当前项目下分支下执行 git push origin -d 旧分支名称 git push origin 新分支名称 tips: 本地分支重命名。如果分支尚未推送到远程&#xff0c;可以使用命令“git branch -m 旧名称 新名称”来重命名本地分支。 远程分支重命名。首先&#xff0c;重命名本地分支&#xff08;与…

C++ 内存管理

目录 一、new 二、delete 一、new 动态申请空间 //动态申请 1 个 int 类型的空间 int* p1 new int;//动态申请 1 个 int 类型的空间并初始化为 0 int* p2 new int(0);//动态申请 10 个 int 类型的空间 int* p3 new int[2]; 二、delete 释放空间 //释放 p1 delete p1;/…