AnnictのGraphQL APIを使ってアニメデータを取得しよう

アニメ視聴記録Webサービス「[Annict](https://annict.com)」のGraphQL APIがリリースされました。まだ粗削りですが、すでに[既存のREST API](https://docs.annict.com/ja/api/v1/overview.html)とほぼ同等のことができるようになっています。

[Annict Blog — GraphQL API \(Beta\) を公開しました](http://blog.annict.com/post/161131210918/graphql-api-beta)

この記事ではそのGraphQL APIを使用してアニメデータを取得する方法をチュートリアル形式でご紹介します。


## 環境

- macOS Sierra 10.12.5
- GraphiQL.app 0.5.1


## アクセストークンを生成する

GraphQL APIにアクセスするにはAnnictのアクセストークンが必要になります。アクセストークンを生成する方法は2つあります。

1. アプリを作ってOAuth認証する
2. 「個人用アクセストークン」を利用する

今回は2の個人用アクセストークンを利用して生成します。

まず https://annict.com/settings/apps にアクセスします。そして「個人用アクセストークン」の「新規作成」ボタンをクリックします。

![アプリケーション | Annict 2017-05-27 04-14-51.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/7cd795c4-128b-36e4-110e-9c6b1e553dbf.jpeg)

作成ページに行くと下の画像のような入力欄が表示されます。「トークンの説明」には適当に利用用途などを入力します。「スコープ」は「読み込み専用」を選択します。今回はアニメのデータを取得するだけで、書き込みは行わないためです。

![個人用アクセストークン作成 | Annict 2017-05-27 04-17-01.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/1cf8a06d-4a37-c66a-bf13-f9c0ec3c1ced.jpeg)

「作成する」ボタンを押すと以下のようにアクセストークンが表示されます。ページをリロードなどすると表示されなくなるので、クリップボードにコピーしておきます。

![アプリケーション | Annict 2017-05-27 04-20-25.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/5c33cc0c-4136-ce89-3673-a7e3de7c0e1b.jpeg)

これでアクセストークンが手に入りました。


## GraphiQL.appをインストールする

GraphQLのクエリを書いて実行するとき「[GraphiQL](https://github.com/graphql/graphiql)」が便利です。これはWebブラウザ上で動くGraphQLのIDEになります。今回はそのGraphiQLのMacクライアントとなる「[GraphiQL.app](https://github.com/skevy/graphiql-app)」を使用します。
GraphiQL.appはHomebrewでインストールできます。

```
$ brew cask install graphiql
```


## GraphQL APIが呼べるようにGraphiQL.appを設定する

以下の2つをGraphiQL.appに設定します。

1. GraphQL APIのエンドポイントURLを指定する
2. 最初に取得したアクセストークンをリクエストヘッダに登録する

GraphiQL.appを立ち上げると下の画像ようなウィンドウが表示されます。「Welcome to GraphiQL」と書かれている左側のカラムがGraphQLのクエリを入力する場所で、その右はクエリの実行結果を表示する場所になります。ちなみに「Welcome to GraphiQL」はコメントなので、消してしまって問題ありません。(スクショでは右側にエラーが出ちゃってますが気にしないでください…)

![GraphiQL 2017-05-27 04-34-50.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/4edc39f6-00cd-8f3f-98e4-a645c4af5d62.jpeg)

「GraphQL Endpoint」の入力欄に下記エンドポイントを入力します。

```
https://api.annict.com/graphql
```

![GraphiQL 2017-05-28 00-50-35.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/6e51eb35-bdde-a986-0ae7-9377a63f0224.jpeg)

GraphQL APIにリクエストを投げるとき、エンドポイントは常にこのURLになります。

次にアクセストークンをヘッダに登録します。「Edit HTTP Headers」という青いボタンをクリックすると、リクエストヘッダを設定することができます。

![GraphiQL 2017-05-27 04-39-00.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/45456052-a340-022f-d6a2-beb903b40963.jpeg)

「Add Header」をクリックして以下のように `Authorization` ヘッダを設定します。

![GraphiQL 2017-05-27 04-40-48.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/3ac1e5ce-8602-b51d-2d2b-6d7124d58c1c.jpeg)

- Header name: `Authorization`
- Header value: `Bearer (アクセストークン)`

以上でGraphiQL.appの設定が終わりました。


## Annictからデータを取得する

一通り設定が終わったので、あとはGraphQLのクエリを書いてデータを取得するだけです。まず手始めに、アクセストークンを生成したユーザ (つまり自分) の情報を取得してみます。

左側のクエリ入力欄に以下のクエリを書いてみます。

```
query {
  viewer {
    username
    name
  }
}
```

`viewer` はAnnictが用意しているクエリで、クエリ実行者の情報 (`User` 型) を返します。([viewerについてのドキュメント](https://docs.annict.com/ja/api/graphql/query.html#viewer-user))
上の例では、ユーザ名 (`username`) と名前 (`name`) だけを取得しています。

クエリを入力したあと、入力欄の上にある再生ボタンみたいなものをクリックすると、右側に取得結果が表示されます。

![GraphiQL 2017-05-28 00-52-24.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/8a6a536c-49af-5b17-66ce-3cc9f5578d42.jpeg)

`User` 型にはユーザ名や名前以外にも様々なフィールドが存在します。詳細は[ドキュメント](https://docs.annict.com/ja/api/graphql/objects/user.html)をご覧ください。


## アニメデータを取得する

GraphQLのクエリ実行まで一通り触れたので、次はいよいよアニメデータを取得します。今回は以下のようなデータを取得したいと思います。

1. 2017年春アニメの中から
2. アニメのタイトルと、「見てる」「見たい」にしている人の数 (ウォッチャー数) だけ取得して
3. ウォッチャー数が多い順に3件取得して
4. それぞれのエピソードも取得する

条件別に箇条書きにしました。AnnictのREST APIでこの条件のデータを取得するには、

1. `GET /v1/works` を1回呼び出して1~3までの条件に該当するアニメを取得する
2. `GET /v1/episodes` を3回 (取得したアニメの数だけ) 呼び出して4のエピソードデータを取得する

といった具合に合計4回リクエストを投げなければいけませんでした。(あくまでAnnictのREST APIがこなれていないだけで、ちゃんとしたREST APIだとそうでもないかもです)
GraphQL APIを使うと、上記のアニメデータを1回のリクエストで取得できます。

少し話が脱線したので元に戻ります。4つの条件をそれぞれクエリに落とし込んでいきます。

まずは1の「2017年春アニメの中から」は以下のように書くことができます。

```
query {
  searchWorks(seasons: ["2017-spring"]) {
  }
}
```

[`searchWorks`](https://docs.annict.com/ja/api/graphql/query.html#searchworks-workconnection) はAnnictが用意しているクエリで、各種条件に該当するアニメが取得できます。その「各種条件」は引数で指定することができ、今回は `seasons` というオプションを使用して「2017年春アニメ」だけを取得するようにしています。なお `seasons` は値に配列が渡せるようになっているため、例えば2017年冬アニメと春アニメを一気に取得することも可能です。

```
query {
  searchWorks(seasons: ["2017-winter", "2017-spring"]) {
  }
}
```

2の「アニメのタイトルと、「見てる」「見たい」にしている人の数 (ウォッチャー数) だけ取得して」は以下のように書くことができます。

```
query {
  searchWorks(seasons: ["2017-spring"]) {
    edges {
      node {
        title
        watchersCount
      }
    }
  }
}
```

`edges` や `node` といったものが出てきました。これはGraphQLが推奨しているページネーションのデータ構造に則ったフィールドになります。詳細は「[Pagination \| GraphQL](http://graphql.org/learn/pagination/)」をご覧ください。

基本的には `node` の中に各型が持つフィールドを指定します。`searchWorks` は[WorkConnection型](https://docs.annict.com/ja/api/graphql/objects/work-connection.html)を通して[Work型](https://docs.annict.com/ja/api/graphql/objects/work.html)を返すため、アニメタイトルを表す
 `title` や、ウォッチャー数を表す `watchersCount` を指定することができます。

上記のクエリは実行可能です。実行すると以下のように2017年春アニメのタイトルとウォッチャー数が取得できたかと思います。

![GraphiQL 2017-05-28 00-53-07.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/23fbfa54-88aa-6ffb-b025-83d234e2746e.jpeg)

3の「ウォッチャー数が多い順に3件取得して」は `searchWorks` の引数に `orderBy` オプションと `first` オプションを指定して実現できます。

```
query {
  searchWorks(
    seasons: ["2017-spring"],
    orderBy: { field: WATCHERS_COUNT, direction: DESC },
    first: 3
  ) {
    edges {
      node {
        title
        watchersCount
      }
    }
  }
}
```

まず `orderBy` オプションですが、こちらは `field` と `direction` というキーを持つオブジェクトを値にします。`field` ではソートしたいフィールドを指定し、`direction` では順序を指定します。今回の例だとそれぞれ `WATCHERS_COUNT`, `DESC` を渡しているので、「ウォッチャー数が多い順に並べる」という意味になります。

`first` オプションは値に数値を指定することができます。指定した数値分最初に該当するデータを取得することができます。`orderBy` オプションで並び替えをしているため、「ウォッチャー数が多いものから3件」という条件になります。

上記コマンドを実行すると、Annict上でウォッチャー数の多い3件のアニメだけが取得できたかと思います。紗霧ちゃんかわいいよ紗霧ちゃん。

![GraphiQL 2017-05-28 00-53-38.jpg](https://qiita-image-store.s3.amazonaws.com/0/168/4ad273db-fe54-8962-dcbd-f31ff910c500.jpeg)

ここまでちゃんとGraphiQL.appを使ってクエリを書いて下さっている方はもうお気づきかと思いますが、GraphiQLのクエリ編集機能はフィールドや引数などの自動補完が効きます。これがとても便利で、知らないGraphQL APIでも何となく中のデータ構造がわかっているような場合は勘でクエリを書くことができます。

![Untitled.gif](https://qiita-image-store.s3.amazonaws.com/0/168/22b096d4-1ffb-cfaa-b5c8-6b755c1fc0cb.gif)

勘で書くのが難しい場合も、ドキュメント参照機能でその型がどんなフィールドを持っているかといった情報をサッと見ることができます。

![Untitled.gif](https://qiita-image-store.s3.amazonaws.com/0/168/676b3c96-f309-a423-21d6-69e1c2494723.gif)

また脱線してしまいました。最後の条件である「それぞれのエピソードも取得する」は以下のように実現できます。

```
query {
  searchWorks(
    seasons: ["2017-spring"],
    orderBy: { field: WATCHERS_COUNT, direction: DESC },
    first: 3
  ) {
    edges {
      node {
        title
        watchersCount
        episodes(
          orderBy: { field: SORT_NUMBER, direction: ASC },
          first: 2
        ) {
          edges {
            node {
              number
              title
            }
          }
        }
      }
    }
  }
}
```

Work型から `episodes` というフィールドが参照できるので、それを呼び出しています。しれっとソート番号順に2件だけ取得するようにしていますが、この `episodes` フィールドも `searchWorks` と同じように引数にオプションを指定してソート順や取得件数を調整することができます。もちろん `number` や `title` だけを取得するといったフィールドの絞り込みも可能です。


## 終わりに

チュートリアルは以上です。実際は単にデータを取得するだけではなく、取得したデータをゴニョゴニョしてWebサイトやアプリ等に表示されることになるかと思います。そういったときは各言語のGraphQLクライアントライブラリを使うことになります。例えばRubyでは「[github/graphql\-client](https://github.com/github/graphql-client)」が一番よく使われている雰囲気を感じます。各言語のライブラリは「[awesome\-graphql](https://github.com/chentsulin/awesome-graphql)」などで確認できます。

このドキュメントをきっかけにAnnictのGraphQL APIが使われたアプリやサービス等が生まれたら幸いです。


## リンク

- https://annict.com
- [AnnictのGraphQL APIの概要](https://docs.annict.com/ja/api/graphql/overview.html)