每一个GraphQL服务都会定义一套类型,用来描述你查询的数据。每个查询到来,服务器会根据schema进行验证并执行查询。

Query类型

  • 严格来说Query是一种对象类型
  • Query是所有查询的入口点
  • Query是必需的,并且有且只有一个

    标量类型(Scalar Types)

    在Graphql中自带了一组标量类型:

  • Int:有符号32为整数

  • Float:有符号双精度浮点值
  • String:UTF-8字符序列
  • Boolean:True或False
  • ID:表示一个唯一标识符,通常用以重新获取对象或作为缓存中的键。使用String一样的方式进行序列化

    数组类型

    使用[]来表示列表,如: ```javascript type Job { title: String salary: Float }

type user { name: String age: Int hobbies: [String] jobs: [Job] }

  1. 其中hobbiesString列表,jobsJob类型的列表。注意查询jobs必须指定Job的字段,如:
  2. ```javascript
  3. {
  4. user {
  5. name
  6. hobbies
  7. jobs {
  8. title
  9. salary
  10. }
  11. }
  12. }

对象类型(Object Types)

我们可以在Graphql定义类型:

  1. type Character {
  2. name: String!
  3. appearsIn: [Episode!]!
  4. }

Character 就是一个GraphQL对象类型,其中 nameappearsInCharacter类型上的字段。并且name字段是String非空的,appearsIn是一个非空的Episode数组,并且数组Episode元素不为空。
⚠️对象查询时,必须指定查询的字段(不能只写变量名直接查询),如:

  1. {
  2. character {
  3. name
  4. appearsIn
  5. }
  6. }

非空类型

默认情况下,每种类型都可以为空。如果指定类型不能为空,可以加 ! 。如 String! 表示非空字符串。

查询参数

在GraphQL中,Schema类型查询支持指定参数,如下:

  1. // 定义数据 文章列表
  2. const articles = [
  3. {id:1, title: 'Java编程思想', publish:'2001-10-01'},
  4. {id:2, title: 'React编程指南', publish:'2003-05-01'},
  5. {id:3, title: 'GraphQL使用教程', publish:'2010-10-01'}
  6. ]
  7. // 定义schema
  8. const schema = buildSchema(`
  9. type Article {
  10. id: ID!
  11. title: String!
  12. publish: String!
  13. }
  14. type Query {
  15. articles: [Article]
  16. article(id: ID!): Article
  17. }
  18. `)
  19. // 定义 resolver
  20. const rootValue = {
  21. // 无参函数
  22. articles() {
  23. return articles
  24. }
  25. // 有参函数
  26. article({id}) {
  27. return articles.find(article => article.id === id)
  28. }
  29. }

修改 & 输入类型

GraphQL支持定义输入类型,对数据进行修改,如下:

  1. // 定义schema (修改)
  2. // 修改类型 关键字为 type Mutation
  3. const schema = buildSchema(`
  4. type Mutation {
  5. deleteArticle(id: ID!): Article
  6. }
  7. `)
  8. // 定义 resolver
  9. const rootValue = {
  10. deleteArticle({id}) {
  11. const article = articles.find(article => article.id === id)
  12. const i = articles.indexOf(article)
  13. if (-1 === i) {
  14. console.log("删除文章不存在");
  15. return null;
  16. }
  17. console.log("删除文章:" + i);
  18. articles.splice(i, 1)
  19. return article
  20. }
  21. }

客户端查询如下:

  1. mutation {
  2. deleteArticle(id: "1") {
  3. id
  4. title
  5. }
  6. }

需要显示指定mutation执行。 {}等价于 query {} 操作还可以定义名称: mutation delete { deleteArticle(id: “1”) { id title } }

对于参数列表很多时,我们可以定义 input 输入对象,如下:

  1. // 定义schema (修改)
  2. // 修改类型 关键字为 type Mutation
  3. const schema = buildSchema(`
  4. input ArticleInput {
  5. title:String!
  6. publish:String!
  7. }
  8. type Mutation {
  9. addArticle(article:ArticleInput):[Article]
  10. }
  11. `)
  12. // 定义 resolver
  13. const rootValue = {
  14. addArticle({article}) {
  15. article.id = uuidv4()
  16. articles.push(article)
  17. return articles
  18. }
  19. }

客户端查询如下:

  1. mutation add {
  2. addArticle(article: {title:"SQL教程", publish:"2021-01-01"}) {
  3. id
  4. title
  5. }
  6. }

完整脚本如下:

  1. const {buildSchema} = require('graphql')
  2. const express = require('express')
  3. const { graphqlHTTP } = require('express-graphql')
  4. const cors = require('cors')
  5. const {v4: uuidv4} = require('uuid')
  6. const app = express()
  7. // 允许客户端进行跨域请求
  8. app.use(cors())
  9. // 定义数据 文章列表
  10. const articles = [
  11. {id:'1', title: 'Java编程思想', publish:'2001-10-01'},
  12. {id:'2', title: 'React编程指南', publish:'2003-05-01'},
  13. {id:'3', title: 'GraphQL使用教程', publish:'2010-10-01'}
  14. ]
  15. // 定义schema
  16. const schema = buildSchema(`
  17. type Article {
  18. id: ID!
  19. title: String!
  20. publish: String!
  21. }
  22. type Query {
  23. articles: [Article]
  24. article(id:ID!):Article
  25. }
  26. input ArticleInput {
  27. title:String!
  28. publish:String!
  29. }
  30. type Mutation {
  31. deleteArticle(id: ID!):Article
  32. addArticle(article:ArticleInput):[Article]
  33. }
  34. `)
  35. // 定义 resolver
  36. const rootValue = {
  37. articles() {
  38. return articles
  39. },
  40. article({ id }) {
  41. console.log(id);
  42. return articles.find(article => article.id === id)
  43. },
  44. deleteArticle({id}) {
  45. const article = articles.find(article => article.id === id)
  46. const i = articles.indexOf(article)
  47. if (-1 === i) {
  48. console.log("删除文章不存在");
  49. return null;
  50. }
  51. console.log("删除文章:" + i);
  52. articles.splice(i, 1)
  53. return article
  54. },
  55. addArticle({article}) {
  56. article.id = uuidv4()
  57. articles.push(article)
  58. return articles
  59. }
  60. }
  61. app.use('/graphql', graphqlHTTP({
  62. schema,
  63. rootValue,
  64. graphiql: true // 开启浏览器 Graphql IDE 调试工具
  65. }))
  66. app.listen(4000, () => {
  67. console.log('Graphql Server is running at http://localhost:4000/graphql')
  68. })

客户端查询:
通过 variables 传递参数进行 query 查询

  1. axios({
  2. method; 'POST',
  3. url: 'http://localhost:4000/graphql',
  4. data: {
  5. query: `
  6. query getArticle($id: ID!) {
  7. article(id: $id) {
  8. id
  9. title
  10. publish
  11. }
  12. }
  13. `,
  14. variables: {
  15. id : 2
  16. }
  17. }
  18. }).then(res => {
  19. console.log(res.data)
  20. })