DEV Community

kaede
kaede

Posted on

GraphQL で StarWars API の planets にネストされた films をとってくる

何がしたいのか

Star Wars API を使って

GraphQL で複数のテーブルが関連したデータを取ってくる練習がしたかった。

appPlanets というエンドポイント?を叩いた。

https://www.back4app.com/database/davimacedo/swapi-star-wars-api/graphql-playground/all-planets

Chrome でアクセスするだけで実行できる
Back4App というところを使った。

https://github.com/graphql/swapi-graphql/blob/7c02fdf5244d8ca66005b9707f634b94364f31c1/schema.graphql#L483

定義はこの公式のスキーマの 483 行目から。


Root -> allPlanets

type Root {
  allFilms(after: String, first: Int, before: String, last: Int): FilmsConnection
  film(id: ID, filmID: ID): Film

  allPlanets(after: String, first: Int, before: String, last: Int): PlanetsConnection
  planet(id: ID, planetID: ID): Planet

  node(
    """The ID of an object"""
    id: ID!
  ): Node
}
Enter fullscreen mode Exit fullscreen mode

Root に AllPlanets が結び付けられている。
そしてそれが PlanetsConnection で Planet を参照しているようだ。


PlannetsConnection -> Planet

type PlanetsConnection {
  totalCount: Int
  planets: [Planet]
}
Enter fullscreen mode Exit fullscreen mode

PlannetsConnection の定義のコードを見ると
planets として Planet の配列が参照されている。

なので今回は planets をエンドポイントとして叩く。


Planet

単体の Planet の定義もみてみる。

type Planet implements Node {
  """The name of this planet."""
  name: String
  gravity: String
  created: String
  id: ID!
}
Enter fullscreen mode Exit fullscreen mode
  • name
  • gravity
  • created
  • id

これらの順番で中身が並べられている。


Back4App で planets の GET を実行する

https://www.back4app.com/database/davimacedo/swapi-star-wars-api/graphql-playground/all-planets

Back4App なら Star Wars API の
リポジトリを clone して npm start しなくても
URL を開くだけで実行できる。

query allPlanets {
      planets (skip: 0, limit: 3) {
        results {
          id,
          name,
          gravity,
          createdAt,
        }
      }
    }
Enter fullscreen mode Exit fullscreen mode

allPlanets という名前(ここは自由)で定義して
planets を叩く。

skip は 0 で最初のひとつめから、
limit は 3 で 3 つだけ

JS の関数の戻り値と似た感じで、
返す値は results で定義するようだ。

呼び出す順番は自由。

{
  "data": {
    "planets": {
      "results": [
        {
          "id": "JNgiSeuJwR",
          "name": "Yavin IV",
          "gravity": "1 standard",
          "createdAt": "2019-12-13T19:42:31.014Z"
        },
        {
          "id": "lZHyO0MIr6",
          "name": "Dagobah",
          "gravity": null,
          "createdAt": "2019-12-13T19:42:31.017Z"
        },
        {
          "id": "PL36fSGLoW",
          "name": "Tatooine",
          "gravity": "1 standard",
          "createdAt": "2019-12-13T19:42:30.901Z"
        }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

結果は json で返ってくる。
data/tableName/results に入っている。

skip を 1 にすると
最初の Yavin IV が skip されて
Alderaan が 3 つめに食い込んでくる。


filmConnection で Planet に結びつく Film も GET する

  filmConnection(after: String, first: Int, before: String, last: Int): PlanetFilmsConnection
Enter fullscreen mode Exit fullscreen mode

Planet には Film とむすびつける
filmConnection というカラムもある。

これは PlanetFilmsConnection を使っていて

type PlanetFilmsConnection {
  pageInfo: PageInfo!
  totalCount: Int
  films: [Film]
Enter fullscreen mode Exit fullscreen mode

このようになっている。

なので、films を追加すれば
惑星に関連するフィルムたちも取れるだろう。

type Film implements Node {
  title: String
  director: String
  releaseDate: String  
}
Enter fullscreen mode Exit fullscreen mode

Film には
title, director, releaseDate,

これらの項目があったのでそれらをいれて

query allPlanets {
      planets (skip: 0, limit: 3) {
        results {
          id,
          name,
          gravity,
          createdAt,
          films {
            results {
              title,
              director,
              releaseDate
            }
          }
        }
      }
    }
Enter fullscreen mode Exit fullscreen mode

planets にリクエスト項目を追加する。

          "createdAt": "2019-12-13T19:42:30.901Z",
          "films": {
            "results": [
              {
                "title": "A New Hope",
                "director": "George Lucas",
                "releaseDate": "1977-05-25T00:00:00.000Z"
              },
              {
                "title": "Attack of the Clones",
                "director": "George Lucas",
                "releaseDate": "2002-05-16T00:00:00.000Z"
              },
Enter fullscreen mode Exit fullscreen mode

すると、films の項目で
惑星データに関連する映画のタイトル、監督、公開日、これらが取れた。


まとめ

GraphQL をてっとり早く試すには

Back4App の Starwars API の
Planets と Films のデータが便利。

type Root {
  allPlanets(after: String, first: Int, before: String, last: Int): PlanetsConnection
}
Enter fullscreen mode Exit fullscreen mode

Root で allPlanets として PlanetsConnection
が結びついている。

なので allPanets というエンドポイントが発生すると推測する。

type PlanetsConnection {
  totalCount: Int
  planets: [Planet]
}
Enter fullscreen mode Exit fullscreen mode

PlanetsConnection が planets として
Planet たちの配列を取っている。

type Planet implements Node {
  name: String
  id: ID!
}
Enter fullscreen mode Exit fullscreen mode

そして Planet の内部に id や name などのカラムが入っている。

query allPlanets {
      planets (skip: 0, limit: 3) {
        results {
          id,
          name,
Enter fullscreen mode Exit fullscreen mode

この形でリクエストする。results の中にカラムを書く。

  filmConnection(after: String, first: Int, before: String, last: Int): PlanetFilmsConnection
Enter fullscreen mode Exit fullscreen mode

Planet の中にさらに filmConnection という
Planet と Films を結びつけるカラムがあり
PlanetFilmConnection を呼び出している

type PlanetFilmsConnection {
  pageInfo: PageInfo!
  totalCount: Int
  films: [Film]
Enter fullscreen mode Exit fullscreen mode

PlanetFilmsConnection には films として
Film たちの配列が入っている。

これをリクエストするには、

query allPlanets {
      planets (skip: 0, limit: 3) {
        results {
          id,
          name
          films {
            results {
              title,
              director,
              releaseDate
            }
Enter fullscreen mode Exit fullscreen mode

このように、results の films の更に results として
Film のカラムを書いてリクエストする。

以上。

Discussion (0)