# HOW TO GRAPHQLでGraphQLの勉強をはじめました その⑥
# Adding a Database
今回はPrizmaをセットアップしてGraphQLサーバーからデータベースに接続してみる感じ。
# Why Prisma
GraphQLサーバーがどのように動いているかは理解できたはず(驚くほどシンプルですよね?)で、強い型付けなスキーマ定義とGraplhQLエンジンがAPI開発のしんどいところを吸収してくれる様が見て取れたと思います、と。
で、それではGraphQLサーバーの構築の何が難しいのでしょうか??
real-worldのアプリケーションではリゾルバーの実装が非常に複雑になりがちです、と。GraphQLクエリは複数のレベルにネストするけど、それはトリッキーでパフォーマンスの問題になってしまいがち。
例えば、ほとんどの場合、authentication, authorization, pagination, filtering, realtime, integrating with 3rd-party services or legasy systems...といったことを考慮にいれなくてはなりません。
大体の場合、リゾルバの実装は以下の2つのような感じになります(両方凄い説得力があるわけでも無さそうですが…)
データベースにSQLもしくはNoSQLのAPIを使って直接アクセスする 👉 SQLをリゾルバの中で書くと複雑になってすぐに手に負えなくなりがち。でもってSQL自体は文字列なので構造化しにくく、エディタの自動補完機能とかが辛い
ORMを使ってデータベースへのアクセスを抽象化してプログラムからアクセスさせる 👉 単純なものには良いアプローチだけど、複雑なクエリやエッヂケースに対応が難しい場合がある
Prismaは上記のような課題を解決し、あなたのリゾルバをよりシンプルに保ってくれるデータアクセスレイヤのソリューションです、と。
# Architecture
以下がPrismaを使った場合のアーキテクチャのオーバービューです。
API Server (graphql-yogaを使って構築してきたようなもの)にPrisma Clientを適用することで(アプローチとしてはORMに近い)、簡単にPrisma Serverを通してデータベースにアクセスできる、というもの。
# Setting up Prisma with a demo database
ミニマムなセットアップではじめます。ファイルを2つ作ってprismaというディレクトリに配置します。
mkdir prisma
touch prisma/prisma.yml
touch prisma/datamodel.prisma
prisma.ymlはPrismaの設定ファイル。datamodel.prismaはあなたのデータモデルの定義すなわちあなたのアプリケーションのmodel。それぞれのmodelはデータベースのテーブルにマッピングされる。
Hacker NewsクローンアプリのデータタイプはLinkしかありません。PrismaはGraphQL SDLをモデル定義に使うので、schema.graphqlのLinkの定義をdatamodel.prismaに移植すれば良い感じ。
ということでdatamodel.prismaを開いて以下のコードを足していきます。
type Link {
id: ID! @id
createdAt: DateTime! @createdAt
description: String!
url: String!
}
schema.graphqlとの違いは @id のところ。これによってPrismaはLinkレコードにユニークなIDを自動生成してデータベースのidフィールドに値を保存します、と。そして、createdAtのところはPrismaがよろしくレコードを作成した日を付けてくれるし、 @updateAtを使えば最後にレコードが更新されたのがいつかを保存してくれます。
次に prisma.yml。以下を追加します。
# The HTTP endpoint for your Prisma API
endpoint: ''
# Points to the file that contains your datamodel
datamodel: datamodel.prisma
# Specifies language & location for the generated Prisma client
generate:
- generator: javascript-client
output: ../src/generated/prisma-client
- endpoint: Prisma APIのHTTPエンドポイント
- datamodel: APIサーバーで使うPrisma clientのデータモデルファイル
- generate: Prisma clientとして自動生成されるものを言語と共に指定
yarnでPrismaのCLIをインストール
yarn global add prisma
今回のチュートリアルではPrisma Cloudと呼ばれる環境にあるデモ用のAWSのAurorをタダで使えるそうです。
ということで👇。対話型のインターフェースで諸々やってくれます。Dockerイメージとして自分のローカルとかで動かしたりも出来るようですが、とりあえず全ておまかせの方向で。
$ prisma deploy
? Set up a new Prisma server or deploy to an existing server? Demo server + MySQL database
Opening https://app.prisma.io/cli-auth?secret=$2a$08$7ImeVvVkrKtdmAxnU0/Uhu in the browser
Authenticating ✔
Authenticated with xxx@xxx.com
? Choose the region of your demo server xxx-xxxx-e75aef/demo-us1
? Choose a name for your service hackernews-node
? Choose a name for your stage dev
Written endpoint `https://us1.prisma.sh/xxx-xxxx-e75aef/hackernews-node/dev` to prisma.yml
Creating stage dev for service hackernews-node ✔
Deploying service `hackernews-node` to stage `dev` to server `prisma-us1` 1.3s
Changes:
Link (Type)
+ Created type `Link`
+ Created field `id` of type `ID!`
+ Created field `createdAt` of type `DateTime!`
+ Created field `description` of type `String!`
+ Created field `url` of type `String!`
Applying changes 979ms
Generating schema 24ms
Saving Prisma Client (JavaScript) at /Users/xxxx/hackernews-node/src/generated/prisma-client
Your Prisma endpoint is live:
HTTP: https://us1.prisma.sh/eiji-shinohara-e75aef/hackernews-node/dev
WS: wss://us1.prisma.sh/eiji-shinohara-e75aef/hackernews-node/dev
You can view & edit your data here:
Prisma Admin: https://us1.prisma.sh/eiji-shinohara-e75aef/hackernews-node/dev/_admin
そしてPrisma APIを通してデータベースとやりとりできるように prisma generate コマンドで prisma.yml を元に自動生成されます。
$ prisma generate
Generating schema 20ms
Saving Prisma Client (JavaScript) at /Users/xxxx/hackernews-node/src/generated/prisma-client
自動生成されたコードは hackernews-node/src/generated/prisma-client のパスに保存されます。これをimportして👇のようなシンプルなNodeのスクリプトを書くことができます。Linkをcreateしてから全て読み込んでprintする的な。またTypeScript定義も生成されるので、これによってVisual Studio Codeなどを使うとIDEで自動補完とかも出来るようになる、と。
const { prisma } = require('./generated/prisma-client')
async function main() {
// Create a new link
const newLink = await prisma.createLink({
url: 'www.prisma.io',
description: 'Prisma replaces traditional ORMs',
})
console.log(`Created new link: ${newLink.url} (ID: ${newLink.id})`)
// Read all links from the database and print them to the console
const allLinks = await prisma.links()
console.log(allLinks)
}
main().catch(e => console.error(e))
次の章ではAPIを進化させGraphQLサーバーとPrismaクライアントを使ってデータベースにアクセスするようなリゾルバ半クションを作っていきます。