SlideShare a Scribd company logo
1 of 55
Download to read offline
GraphQL
・GraphQLってなに?

 RESTとの違いなど
・GraphQLのスキーマ

 Query と Mutation
・GraphQL DeepDive
今日お話しすること
?
WebAPI
WebApp (SPA)
iOS App
Android App
http/s
バックエンド
json
REST

JSON-RPC

GraphQL
フロントエンド
昨今のアプリ
・WebAPIで流行っているアーキテクチャ
・分かりやすい統一されたインターフェース



  GET /Users - ユーザ一覧を取得

  GET /Users/999 - ID:999ユーザを取得

  POST /Users - ユーザを登録

  PUT /Users/999 - ID:999ユーザを更新

  DELETE /Users/999 - ID:999ユーザを削除
・Twitter, Amazon, Facebook, Githubなどで採用!
RESTいいよね!
でも・・・つらい
コメント一覧
フィード一覧
コメントのコメント一覧
いいね一覧
友達一覧
コメントのいいね一覧
何がつらいか?
・関連リソース

 記事一覧、コメント一覧…etc

 通信が増えてレンダリングが遅く。
・いらない項目

 ユーザのニックネームだけ表示に

 使いたいのに住所情報まで取れたり。
・互換性の維持

 APIのバージョニング。
RESTのつらさ
なに?

・Facebookが2012年から開発

・API向けのクエリ言語

・仕様であり実装ではない


特徴は?

・1リクエストで関連リソースを一気に取得!

・クライアントが使う必要なデータだけを抽出!
http://graphql.org/code/
そこで ですよ
RESTful
GraphQL
最近グググーってきてます
Github の採用が後押し
GraphQL
Netflixが開発した
           ってのもある
参考までに
!
・Schema と Types

 GraphQL schema languageを使って

 Queries と Mutationの構造を定義
・Queries と Mutation

 Queries :データ取得


 Mutations:データ変更
GraphQL
schema {

query : Query

mutation : Mutation

}
schema
ここでのQueryとMutationは型。

Query と Mutationをさらに定義していく。
Query Schema
type Character {    … GraphQL Object Type

name: String!     … 文字列、Nullはダメ

appearsIn: [Episode]! … Episode の配列 … [] or [a,b]

}
enum Episode { … ENUMも定義できる

NEWHOPE

EMPIRE

JEDI

}
使える型 … Int / Float / String / Boolean / ID / 自分が定義したtype
Object types と fields
myField : [String!]
myField: null // ok

myField: [] // ok

myField: [a,b] // ok

myField: [null,a] // ng
myField : [String]!
myField: null // ng

myField: [] // ok

myField: [a,b] // ok

myField: [null,a] // ok
List と Non-Null
「!」の位置で意味が変わるよ
type Character {

id : ID!

name : String!

length(unit: LengthUnit = METER) : Float

}
Arguments
引数を持たせることもできる
interface Character {

id : ID!

name : String!

}
type Human implements Character {

id : ID!

name : String!

starships : [Starship]

}
type Droid implements Character {

id : ID!

name : String!

primaryFunction : String

}
interfaces
Droid にしかないフィールド
interfaces
Droidの時は取得ってやる
エラーになる!
union SearchResult = Human | Droid | Starship
Union Types
複数の型をまとめて定義することができるが
個人的にこのレスポンスは情報が混ざっていて嫌い
type Query {

hero(episode: Episode) : Character

droid(id : ID!) : Droid

}
Query
最後に統合してQueryを定義
Mutation Schema
input ReviewInput {

stars : Int!

commentary : String

}
・input には input型しか参照できない

・Argumentsも使用できない

input
mutation CreateReviewForEpisode($ep: Episode!, $re : ReviewInput) {

createReview(episode: $ep, review:$re) {

stars

commentary

} 

}
mutation
変数
・エピソードとレビューを受けて、レビューを作成

・クライアントにはスターと解説を返却する
type Mutation {

createReview(episode: $ep, review:$re) : CreateReviewForEpisode

}
Mutation
最後に統合してMutationを定義
Query
{

hero {

name

}

}
{

"data": {

"hero": {

"name": "R2-D2"

}

}

}
Request Response
Queries - Fields
取得するフィールドを明示的に指定するので

フィールドが増えても無駄な通信量が増えない
つまり「name」を「fullname」に仕様変更する時

新フィールドで追加してもクライアントには影響なし!
{

human(id: "1000") {

name

height(unit: FOOT)

}

}
{

"data": {

"human": {

"name": "Luke Skywalker",

"height": 5.6430448

}

}

}
Request Response
Queries - Arguments
id:1000を頂戴
単位はfootで
{

empireHero: hero(episode: EMPIRE) {

name

}

jediHero: hero(episode: JEDI) {

name

}

}
{

"data": {

"empireHero": {

"name": "Luke Skywalker"

},

"jediHero": {

"name": "R2-D2"

}

}

}
Request Response
Queries - Aliases
episodeがEMPIREのデータは「empireHero」

JEDIのデータは「jediHero」というフィールドで取得
{

leftComparison: hero(episode: EMPIRE) {

...comparisonFields

}

rightComparison: hero(episode: JEDI) {

...comparisonFields

}

}

fragment comparisonFields on Character {

name

appearsIn

friends {

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"}

]}}}
Request Response
Queries - Fragments
再利用可能なフィールドセットを定義できる
query HeroNameAndFriends($episode: Episode)
{

hero(episode: $episode) {

name

friends {

name

}

}

}
VALIABLES

{

"episode": "JEDI"

}
{

"data": {

"hero": {

"name": "R2-D2",

"friends": [

{

"name": "Luke Skywalker"

},

{

"name": "Han Solo"

},

{

"name": "Leia Organa"

}

]

}

}

}
Request Response
Queries - Variables
値を外部から渡す
Mutation
mutation CreateReviewForEpisode($ep: Episode!,
$review: ReviewInput!) {

createReview(episode: $ep, review: $review) {

stars

commentary

}

}
VARIABLES

{

"ep": "JEDI",

"review": {

"stars": 5,

"commentary": "This is a great movie!"

}

}
{

"data": {

"createReview": {

"stars": 5,

"commentary": "This is a great
movie!"

}

}

}
Request Response
Mutations
・エピソードとレビューを受けて、レビューを作成

・クライアントにはスターと解説を返却する
・Validation
・Execution
・Introspection
Deep Dive
Validation
Queryのチェック
{

hero {

...NameAndAppearances

friends {

...NameAndAppearances

friends {

...NameAndAppearances

}

}

}

}
fragment NameAndAppearances on Character {

name

appearsIn

}
{

"data": {

"hero": {

"name": "R2-D2",

"appearsIn": [

"NEWHOPE",

"EMPIRE",

"JEDI"

],

"friends": [

{

"name": "Luke Skywalker",

"appearsIn": [

"NEWHOPE",

"EMPIRE",

"JEDI"

],

"friends": [

{

"name": "Han Solo",

"appearsIn": [
Request Response
階層数チェック
fragment の無限循環が起きないように循環参照はエラーとする
他にも
・存在しないフィールドの指定

・型そのものの指定

 ({ hero } -> { hero {name} }

・異なるインターフェースのフィールド


GraphQLは仕様なので実装は自分でやる
Execution
やってみよう!
Base Information
{
"data": {
"human": {
"name": "Han Solo",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"starships": [
{
"name": "Millenium Falcon"
},
{
"name": "Imperial shuttle"
}
]
}
}
}
Schema Query Request Response
Query: {

human(obj, args, context) {

return context.db.loadHumanByID(args.id).then(

userData => new Human(userData)

)

}

}
obj : previous object, ルートではあまり使うことはない

args : query の argument

context : ユーザーやDBアクセスのようなコンテキスト情報を保持
javascript sample
Root type
IDを元にDBからHumanを取得

Promiseを返却
Human: {

name(obj, args, context) {

return obj.name

}

}
Humanオブジェクトが使える状態になったので

フィールドの値も何を返却するのか定義する。
Trivial Resolvers
Human: {

starships(obj, args, context) {

return obj.starshipIDs.map(

id => context.db.loadStarshipByID(id).then(

shipData => new Starship(shipData)

)

)

}

}
List Resolvers
StarshipのID一覧を元にからStarshipを取得

Promiseのリストを返却
Introspection
自己分析
{

__type(name: "Droid") {

name

fields {

name

type {

name

kind

ofType {

name

kind

}

}

}

}

}
スキーマ情報の確認
{

"data": {

"__type": {

"name": "Droid",

"fields": [

{

"name": "name",

"type": {

"name": null,

"kind": "NON_NULL",

"ofType": {

"name": "String",

"kind": "SCALAR"

} } },

{

"name": "friends",

"type": {

"name": null,

"kind": "LIST",

"ofType": {

"name": "Character",

"kind": "INTERFACE"

} } },
定義したスキーマの有効活用!
Express + GraphQL
const schema = buildSchema(`
type Query {
hello: String
world: String
}
`);
const root = {
hello: () => 'Hello!',
world: () => 'World!',
};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000));
sample express
curl localhost:4000/graphql 

-d '{"query":"{hello}"}' 
-H "Content-Type:application/json"
curl localhost:4000/graphql 

-d '{hello}'

-H “Content-Type:application/graphql"
sample curl
application/graphql !!
https://developer.github.com/v4/explorer/
せっかくなのでGithubのGraphQLAPIをさわってみよう
・結局なんだったか

 ・API向けのクエリ言語

 ・仕様であり実装ではない

 ・QueryとMutationを定義する
・何がいいのか

 ・関連リソースを一気に取得!

 ・必要なデータだけを抽出

 ・バージョン互換性問題に強い
まとめ
・実装は難しそう
・性能問題が起きやすそう
・ドキュメントが少ないのがつらい
・RESTの問題を解決しているが

 データ操作系は仕様がブレそう
・BFFにいいかもしれない
所感
Backend For Frontend
WebApp (SPA)
iOS App
Android App
http/s
バックエンド
json
フロントエンド
users
REST

microservice
auth
articles
comments
favorites
GraphQL
試してみよう!

React + GraphQL + Relay
https://facebook.github.io/relay/docs/tutorial.html
♪

More Related Content

Similar to GraphQL

WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話Hidetaka Okamoto
 
ARC-009_RDB 技術者のための NoSQL ガイド
ARC-009_RDB 技術者のための NoSQL ガイドARC-009_RDB 技術者のための NoSQL ガイド
ARC-009_RDB 技術者のための NoSQL ガイドdecode2016
 
LODを使ってみよう!
LODを使ってみよう!LODを使ってみよう!
LODを使ってみよう!uedayou
 
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法  ※講演は翻訳資料にて行います。 - Getting the Best...PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法  ※講演は翻訳資料にて行います。 - Getting the Best...
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...Holden Karau
 
Redis Intro Osc2010 Tokyo Spring
Redis Intro Osc2010 Tokyo SpringRedis Intro Osc2010 Tokyo Spring
Redis Intro Osc2010 Tokyo SpringMakoto Ohnami
 
【とらラボLT】go言語でのweb apiの作り方3選
【とらラボLT】go言語でのweb apiの作り方3選【とらラボLT】go言語でのweb apiの作り方3選
【とらラボLT】go言語でのweb apiの作り方3選虎の穴 開発室
 
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...Shohei Okada
 
JSON-LD schema.org定義によるデータ構造化のススメ
JSON-LD schema.org定義によるデータ構造化のススメJSON-LD schema.org定義によるデータ構造化のススメ
JSON-LD schema.org定義によるデータ構造化のススメTakami Kazuya
 

Similar to GraphQL (9)

WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話
 
ARC-009_RDB 技術者のための NoSQL ガイド
ARC-009_RDB 技術者のための NoSQL ガイドARC-009_RDB 技術者のための NoSQL ガイド
ARC-009_RDB 技術者のための NoSQL ガイド
 
LODを使ってみよう!
LODを使ってみよう!LODを使ってみよう!
LODを使ってみよう!
 
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法  ※講演は翻訳資料にて行います。 - Getting the Best...PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法  ※講演は翻訳資料にて行います。 - Getting the Best...
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...
 
Redis Intro Osc2010 Tokyo Spring
Redis Intro Osc2010 Tokyo SpringRedis Intro Osc2010 Tokyo Spring
Redis Intro Osc2010 Tokyo Spring
 
【とらラボLT】go言語でのweb apiの作り方3選
【とらラボLT】go言語でのweb apiの作り方3選【とらラボLT】go言語でのweb apiの作り方3選
【とらラボLT】go言語でのweb apiの作り方3選
 
第5回LinkedData勉強会@yayamamo
第5回LinkedData勉強会@yayamamo第5回LinkedData勉強会@yayamamo
第5回LinkedData勉強会@yayamamo
 
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
 
JSON-LD schema.org定義によるデータ構造化のススメ
JSON-LD schema.org定義によるデータ構造化のススメJSON-LD schema.org定義によるデータ構造化のススメ
JSON-LD schema.org定義によるデータ構造化のススメ
 

More from Akira Otsuka

XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記
XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記
XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記Akira Otsuka
 
図書館駆動読書 (Toshokan Driven Dokusho)
図書館駆動読書 (Toshokan Driven Dokusho)図書館駆動読書 (Toshokan Driven Dokusho)
図書館駆動読書 (Toshokan Driven Dokusho)Akira Otsuka
 

More from Akira Otsuka (6)

XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記
XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記
XP祭り2019 A-3-1 突然アジャイル人材の育成を任されたエンジニアの奮闘記
 
図書館駆動読書 (Toshokan Driven Dokusho)
図書館駆動読書 (Toshokan Driven Dokusho)図書館駆動読書 (Toshokan Driven Dokusho)
図書館駆動読書 (Toshokan Driven Dokusho)
 
serverless
serverlessserverless
serverless
 
Kibana3
Kibana3Kibana3
Kibana3
 
ict antena
ict antenaict antena
ict antena
 
Ansible入門
Ansible入門Ansible入門
Ansible入門
 

GraphQL