GraphQLでデータ操作をしてみた
IT技術
はじめに
こんにちは、福岡オフィスでWebエンジニアとして働いているずおです!
今回は、GraphQLでデータ操作をしてみるというお題で記事を書いていきたいと思います。
よろしくお願いします。
GraphQLとは
一言で言うと「APIのクエリ言語」です。
REST APIと異なり、GraphQLは、基本的に1つのエンドポイントから、自分が欲しい情報だけを取得することができます。
RESTとGraphQLの対応関係は下記の通りです。
REST | GraphQL | |
---|---|---|
取得 | GET | Query |
登録 | POST | Mutation |
更新 | PATCH | Mutation |
削除 | DELETE | Mutation |
詳しくは、こちらの記事をご参照ください。
では実際に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の初歩的なデータ操作しか扱わなかったので、次回は、フロント側の実装や、もう少し深いところまで記事にできたら良いなと思います。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
愛媛県の田舎町で生まれ育ちましたずおと申します。 趣味はサウナと居酒屋巡りです。 未経験で入社させていただいたので、いち早く戦力になれるように日々頑張ります! 座右の銘は「悩んでるひまに、一つでもやりなよ」 ドラえもんの名言です。よろしくお願いします。