DEV Community

kaede
kaede

Posted on

1 1

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 のカラムを書いてリクエストする。

以上。

Reinvent your career. Join DEV.

It takes one minute and is worth it for your career.

Get started

Top comments (0)

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay