📈

GraphQLを学ぶ その2

2023/01/04に公開

これは何

データの登録・更新・削除

  • Mutationというルート型を使う
    • queryと同じく、引数で特定のデータを指定して実行が可能
      • 必要なフィールドを指定するための選択セットの記述が必要
    • レスポンスにオブジェクトが設定されている場合はそのオブジェクトの値が返ってくる
    • 設定されていない場合は正常に更新されればtrue、異常が発生した場合はfalseが返ってくる
    • 処理内容自体はAPIの実装により異なる
    # 実行内容
    mutation burnUsers {
        deleteAllUser #<-全員削除
    }
    # 全員削除された
    true
    # なんらかで異常発生
    false
    
    # 実行内容
    mutation burnUser {
        deleteUser(id: 1) { #<-選択フィールドで渡される引数を指定する必要がある
            id
            name
        }
    }
    # 削除できた
    {
        "data": {
            "id": 1
            "name": "hoge"
        }
    }
    # なんらかで異常発生
    エラーに関する情報を返す
    
    # 実行内容
    mutation createUser { #<-ユーザーを新規作成
        addUser(name: "fuga", age: 27) { 
            id
            name
            age
        }
    }
    # 作成できた
    {
        "data": {
            "id": 1
            "name": "fuga"
            "age": 27
        }
    }
    # なんらかで異常発生
    エラーに関する情報を返す
    
  • 変数で送る事もできる
    • 変数名の頭に$がつく
    mutation createUser($name:String! $age:Int) {
        addUser(name:$name, age:$age) {
            id
            name
            age
        }
    }
    
  • ここらへんまでは裏側の実装次第だな、という感覚。

WebSocketを使った便利な機能

  • サブスクリプションを使うと、WebSocketを使ってサーバーが更新されるたびに、クライアントでその情報をリアルタイムに受け取る事ができる

  • やり方

    1. クエリを叩ける環境を二つ用意
    2. 一つ目の環境でsubscriptionを実行する
      subscription {
          userChange {
              name
              age
          }
      }
      
      • 実行した段階でWebsocketを通じて通知を受け取れるようになる!
    3. もう一つの環境でmutationを実行
      mutation toAgeUser {
          setUserAge(id: "1", age: 29) { #<- 29歳にする
              name
              age
          }
      }
      
    4. subscriptionを実行していた2の環境で結果が返ってくる
  • snowtooth.moonhighway.comで実際にやってみた

    1. 一つ目の環境でsubscriptionを実施するとグルグルしている
    2. 二つ目の環境でmutationを実施して変更をかける
    3. 一つ目の環境に戻って確認するとデータが取得されている!
      • ちなみに2でエラーが発生した場合は取得されなかった、よかった。
  • 前職でゴリゴリWebSocketを作っていたので、この機能には感動した。

APIスキーマの詳細を取得できるインストロペクション

  • クライアントサイドよりサーバーサイドの意志を知るための方法だな、という印象
  • __schemaでスキーマを取得できる
    query {
    __schema {
        types {
            name
            age
        }
    }
    }
    
  • __typeで型を取得できる
    query userDetails {
        __type(name: "hoge") {
            name
            ages
        }
    }
    

クライアントサイドのGraphQLは文字列をどうやってクエリとして認識をしているのか?

  • 文字列を抽象構文木にパースし、独立したトークンに分解される→字句解析という手法
    • 抽象構文木:構文構造をデータ構造に起こしたもの
  • 一つの問合せ(文字列)にはひとつあるいは複数の定義を持つ
  • それらの定義のことをGraphQLスキーマと呼ぶ(前回のどこで定義してるの?の答えですね)

その2 〆

  • サブスクリプションという機能だけで、GraphQLを使う価値があるなぁと思った(チョロい)
  • 前職でRESTを使っていた時はCDCなどをクライアントとバックエンドの共通言語としていたが、クライアントサイドからスキーマの詳細を取得できるのはバックエンドの知識がなくとも理解することができて良い
  • そしてようやくGraphQLスキーマに辿り着いた。
  • 次回!GraphQLスキーマ 知る。

Discussion