2022/12/29

GitHub GraphQL APIを使って各種データを取得する


GitHubには REST API と GraphQL API の2つのAPIが準備されています。
本記事では、 GraphQL API の方の使い方についてまとめています。

GraphQL APIとは

GraphQLとは、2012年にMeta(旧 Facebook)社が作成したクエリ言語です。
クエリ=問い合わせという意味で、決められたエンドポイントにGraphQLクエリを送信すると、必要なデータを入手したり、何か操作を要求したりすることができます。
特徴として、一般的なREST APIでは複数のURLからデータを読み込む必要がありますが、GraphQL APIでは1回のリクエストで必要データをすべて取得することができます。

以下は公式サイトです。

QraphQLの「Qraph」は、グラフ理論から来ています。
グラフ理論については下記のサイトがわかりやすかったので、ご興味があれば参照ください。

GitHub GraphQL API エクスプローラ

以下はGitHubのGraphQLを実行できるエクスプローラのサイトです。
試しにクエリを実行してみることができます。

クエリの例

下記のクエリは、特定のユーザーの、Forkを除いたレポジトリ数と各レポジトリのデータを取得するものです。
上記のエクスプローラでこれを実行すると、レスポンスデータを見ることができます。

query{
  user(login:"yamaccu") {
    repositories(first:100 ,isFork:false){
      totalCount
      nodes{
        name
        languages(first:10) {
          edges {
            size
            node {
              name
            }
          }
        }
      }
    }
  }
}

このドキュメントに従って、取得したいデータに向かってノードやエッジを繋げていくイメージになります。

クエリに変数を使う

クエリの中に変数を使用することもできます。
以下の例では、ユーザー名のところを「username」という変数にしています。

query($username:String!){
  user(login:$username) {
    repositories(first:100 ,isFork:false){
      totalCount
      nodes{
        name
        languages(first:10) {
          edges {
            size
            node {
              name
            }
          }
        }
      }
    }
  }
}
variables{
   "username": "yamaccu"
}

100以上のデータを扱う

上記のRepositoriesの取得データ数はMAX100となっていますので、それ以上のデータ数を取得する場合はページネーション処理が必要になります。
Repositories配下の「hasNextPage」と「endCursor」を使用します。

repositories {
  pageInfo {
    hasNextPage
    endCursor
  }
}

repositoriesの引数の「after」でカーソルを指定できるので、pageInfo->endCursorで取得した値を次のように設定してもう一度Queryを実行すると、続きのデータを取得することができます。

repositories(first: 100, after: "endCursorの値") {
  ・・・
}

JavaScript(node.js)でAPIを実行してデータを取得

以上の内容を踏まえて、JavaScript (node.js) でGithubのレポジトリデータを取得してみます。

import axios from "axios";

let hasNextPage = true;
let endCursor;
let resData = [];
const token = "xxxxxxxx";
const username = "xxxxxx";
const headers =
{
  Authorization: `token ${token}`,
};
const variables = 
{
  login: username
};

let i = 0;
while (hasNextPage) {
  let data =
  {
    query: `
      query userInfo($login: String!) {
        user(login: $login) {
          repositories(ownerAffiliations: OWNER, isFork: false, first: 100, ${endCursor ? `after: "${endCursor}"` : ''}) {
            pageInfo{
              hasNextPage
              endCursor
            }
            nodes {
              name
              languages(first: 10, orderBy: {field: SIZE, direction: DESC}) {
                edges {
                  size
                  node {
                    color
                    name
                  }
                }
              }
            }
          }
        }
      }
      `,
    variables,
  };

  let res = await axios({
    url: "https://api.github.com/graphql",
    method: "post",
    headers,
    data,
  });

  hasNextPage = res.data.data.user.repositories.pageInfo.hasNextPage;
  endCursor = res.data.data.user.repositories.pageInfo.endCursor;

  resData[i] = res.data;
  i++;
}

以上です。




コメント(githubのアカウントが必要です)