• トップ
  • ブログ一覧
  • GraphQLでデータ操作をしてみた
  • GraphQLでデータ操作をしてみた

    ずお(エンジニア)ずお(エンジニア)
    2023.07.05

    IT技術

    はじめに

    こんにちは、福岡オフィスでWebエンジニアとして働いているずおです!

    今回は、GraphQLでデータ操作をしてみるというお題で記事を書いていきたいと思います。

    よろしくお願いします。

    GraphQLとは

    一言で言うと「APIのクエリ言語」です。

    REST APIと異なり、GraphQLは、基本的に1つのエンドポイントから、自分が欲しい情報だけを取得することができます。

    RESTとGraphQLの対応関係は下記の通りです。

    RESTGraphQL
    取得GETQuery
    登録POSTMutation
    更新PATCHMutation
    削除DELETEMutation

    詳しくは、こちらの記事をご参照ください。

    では実際にGraphQLを利用してみましょう!

    GraphQLサーバー構築

    まずは、ディレクトリを作成し、package.jsonを作成します。

    私はディレクトリ名をgraphql-backendとしました。

    1mkdir graphql-backend
    2cd graphql-backend
    3npm init -y

    次に、apollo/serverとgraphqlライブラリのインストールを行います。

    1npm install @apollo/server graphql

    インストール完了後、package.jsonにライブラリが追加されていればOKです!

    1{
    2  "name": "graphql-backend",
    3  "version": "1.0.0",
    4  "description": "",
    5  "main": "index.js",
    6  "type": "module",
    7  "scripts": {
    8    "test": "echo \"Error: no test specified\" && exit 1"
    9  },
    10  "keywords": [],
    11  "author": "",
    12  "license": "ISC",
    13  "dependencies": {
    14    "@apollo/server": "^4.7.4",
    15    "graphql": "^16.7.1"
    16  }
    17}

    そして、schema.graqhqlファイルを作成し、スキーマを定義していきます。

    1# GraphQLスキーマを定義する
    2type Query {
    3  info: String!
    4  feed: [Link!]!
    5}
    6
    7type Mutation {
    8  post(url: String!, description: String!): Link!
    9}
    10
    11type Link {
    12  id: ID!
    13  description: String!
    14  url: String!
    15}

    次にindex.jsファイルを作成し、先ほど別ファイルで定義したスキーマを読み込みます。

    1import { ApolloServer } from "@apollo/server";
    2import { startStandaloneServer } from "@apollo/server/standalone";
    3import { readFileSync } from "fs";
    4
    5// schema.graphqlファイルを読み込む
    6const typeDefs = readFileSync("./src/schema.graphql", { encoding: 'utf-8' });

    次にリゾルバを定義します。

    スキーマで定義された型の取得方法を定義し、実際にデータ操作を行うのがリゾルバというものになります。

    1// リゾルバを定義する
    2const resolvers = {
    3	Query: {
    4		info: () => `github information`
    5	}
    6};

    スキーマとリゾルバが定義できたら、ApolloServerをインスタンス化し、

    それをstartStandaloneServerに渡し、実際にサーバーが起動できているか確認します。

    1// ApolloServerをインスタンス化する
    2const server = new ApolloServer({
    3	typeDefs,
    4	resolvers
    5});
    6
    7// startStartaloneServer関数にApolloServerインスタンスを渡す
    8const { url } = await startStandaloneServer(server, {
    9  listen: { port: 4000 },
    10});
    11
    12// console.logでサーバーのURLを表示する
    13console.log(`🚀 Server ready at ${url}`);

    無事起動できました😀

    Prisma

    それでは、DBにデータを保存するためprisma、prisma/clientをインストールします

    1npm install prisma --save-dev
    1npm install @prisma/client

    インストール後、初期化処理を行います。

    1npx prisma init

    実行後、prismaディレクトリに、schema.prismaファイルが作成されます。

    今回DBはSQliteを使用します。

    1// This is your Prisma schema file,
    2// learn more about it in the docs: https://pris.ly/d/prisma-schema
    3
    4generator client {
    5  provider = "prisma-client-js"
    6}
    7
    8datasource db {
    9  provider = "sqlite"
    10  url      = "file:./dev.db"
    11}
    12
    13model Link {
    14  id          Int      @id @default(autoincrement())
    15  createdAt   DateTime @default(now())
    16  description String
    17  url         String
    18}

    model作成後、マイグレーションを行います

    1npx prisma migrate dev --name init
    1-- CreateTable
    2CREATE TABLE "Link" (
    3    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    4    "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    5    "description" TEXT NOT NULL,
    6    "url" TEXT NOT NULL
    7);

    マイグレーションファイルが作成されたので、Prisma Clientを再生成します。

    1npx prisma generate

    script.jsファイルを作成し、Prisma Clientでデータベース操作をするためのコードを記述します。

    1// DBにアクセスするためのクライアントライブラリ
    2import { PrismaClient } from "@prisma/client";
    3
    4// PrismClientのインスタンスを作成
    5const prisma = new PrismaClient();
    6
    7async function main() {
    8  const newLink = await prisma.link.create({
    9    data: {
    10      description: "this is zuoboo's github",
    11      url: "https://github.com/zuoboo",
    12    },
    13  });
    14  const allLinks = await prisma.link.findMany();
    15  console.log(allLinks);
    16}
    17
    18main()
    19  .then(async () => {
    20    await prisma.$disconnect();
    21  })
    22  .catch(async (e) => {
    23    console.error(e);
    24    await prisma.$disconnect();
    25    process.exit(1);
    26  });
    1node src/script.js
    2{
    3id: 1,
    4createdAt: 2023-06-25T14:04:24.696Z,
    5description: 'this is zuoboo's github',
    6url: 'https://github.com/zuoboo'
    7},

    ターミナルで確認するとデータが入っているので連携しているようです。
    クライアントとPrismaは連携ができたので、次はサーバーとPrismaを連携してみます。

    index.jsにコンテキストを追加して、リゾルバ関数内で使用できるようにコードを修正します。

    1// リゾルバを定義する
    2const resolvers = {
    3  Query: {
    4    info: () => `github information`,
    5    feed: async (parent, args, context) => {
    6      return context.prisma.link.findMany();
    7    },
    8  },
    9
    10  Mutation: {
    11    post: (parent, args, context) => {
    12      const newLink = context.prisma.link.create({
    13        data: {
    14          description: args.description,
    15          url: args.url,
    16        },
    17      });
    18      return newLink;
    19    },
    20  },
    21};
    22
    23// ApolloServerをインスタンス化する
    24const server = new ApolloServer({
    25  typeDefs,
    26  resolvers,
    27});
    28
    29// startStartaloneServer関数にApolloServerインスタンスを渡す
    30const { url } = await startStandaloneServer(server, {
    31  // contextを追加し、リゾルバに渡す
    32  context: async ({ req, res }) => ({
    33    prisma,
    34  }),
    35  listen: { port: 4000 },
    36});

    Apollo Serverを起動して、データの取得や作成ができるか確認してみます。

    Mutation実行後、

    データが追加されました

    1npx prisma studio

    ちなみに、Prisma Studioを使用すると、データベースの中身をテーブルで確認することもできます!

    終わりに

    記事をご覧いただきありがとうございました。

    今回はバックエンドだけの実装であったことと、GraphQLの初歩的なデータ操作しか扱わなかったので、次回は、フロント側の実装や、もう少し深いところまで記事にできたら良いなと思います。

     

    ずお(エンジニア)

    ずお(エンジニア)

    おすすめ記事