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);
});

歡迎找歪歪梯聊騷

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章