Cloudflare D1を使ってみる

2022.11.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

2022年5月にD1が発表されてから
いつさわれるようになるのかなーと思いつつ待ってましたが、
先日こんな記事が公開されてました。
また、ドキュメントも(alpha版ですが)公開されてます。
実際に試したところ、自分の環境(MBP Apple M1)でも動いたので紹介します。

Miniflareでd1を動かすブランチは前からありましたが

注意

2022/11月現在、Cloudflare D1はalpha版です。
けっこうな頻度で更新されてますし、データが消えたりするかもしれません。
使用は自己責任でお願いします。

Cloudflare D1?

D1は、Cloudflare Workersから使用できる、サーバレスデータベースです。
(Cloudflare pagesでも使えます)

SQLite上に構築されており、Cloudflareのエッジロケーションで提供されます。
以前、mvSQLiteについて書きましたが、
こんな感じの分散データベースを
フルマネージド&エッジロケーションで提供してくれます。

また、2022/5月に発表された記事では、

  • ダッシュボードから簡単な操作で構築を開始できる
  • 面倒な管理は必要なく高速パフォーマンスを実現

とのことです。

Environment

  • MacBook Pro (13-inch, M1, 2020)
  • OS : MacOS 12.4
  • Node : v18.12.1 (v19だと動かなかった)

Try

wranglerのインストールとプロジェクト作成

では、D1のドキュメントに沿って試してみます。
まずはD1対応バージョンのwranglerをインストールします。

% npm install -g wrangler@d1

version確認。

wrangler --version
 ⛅️ wrangler 0.0.0-b918fc06 (update available 0.0.0-c725ce01)

wrangerでプロジェクトd1-alpha-projectという名前で作成します。
必要なファイルが生成されます。

% wrangler init d1-alpha-project -y

データベース作成

Wranglerにログインし、d1 createコマンドでデータベースを作成します。
ここでは"my-d1"という名前のデータベースを作成。

% wrangler login
% wrangler d1 create my-d1
? 'wrangler d1 <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
✅ Successfully created DB 'my-d1'!

Add the following to your wrangler.toml to connect to it from a Worker:

[[ d1_databases ]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "my-d1"
database_id = "<Your Dartabase ID>"

ご丁寧に、wrangler.tomlでデータベースをバインドするための記述も表示してくれます。
なので、↑のd1_databasesセクションの記述をwrangler.tomlに追加しましょう。
bindingに指定した値でworkersからアクセス可能になります。

データベースができているかd1 listコマンドで確認します。

% wrangler d1 list
? 'wrangler d1 <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
┌──────────────────────────────────────┬────────────┐
│ uuid                                 │ name       │
├──────────────────────────────────────┼────────────┤
│ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx │ my-d1      │
└──────────────────────────────────────┴────────────┘

D1データベースにアクセスする

サンプル用SQLをschema.sqlという名前で
d1-alpha-projectディレクトリに作成します。

DROP TABLE IF EXISTS Users;
CREATE TABLE Users (id INT, name TEXT, age INT, PRIMARY KEY (`id`));
INSERT INTO Users (id, name, age) VALUES (1, "Taro", 30),(3, "Hanako", 35),(5, "Tom", 40);

d1 executeでschema.sqlを指定し、データベースに対してSQLを実行します。
--localオプションをつけると、ローカルのデータベースに対して実行されます。

% wrangler d1 execute my-d1 --file=./schema.sql --local
・
・
Executing on my-d1 (xxxxxxxxxxxxxx):
Executed command in ms.

d1 executeではSQLを直接指定することもできます。

% wrangler d1 execute my-d1 --command='SELECT * FROM Users' --local
・
・
Executing on my-d1 (xxxxxxxxxxxxxx):
┌─────┬────┬────────┐
│ age │ id │ name   │
├─────┼────┼────────┤
│ 30  │ 1  │ Taro   │
├─────┼────┼────────┤
│ 35  │ 3  │ Hanako │
├─────┼────┼────────┤
│ 40  │ 5  │ Tom    │
└─────┴────┴────────┘

この時点でCloudflareのダッシュボードでd1のところ(Workers -> D1)を見ると、
作成したmy-d1データベースができてます。
ここではテーブルのデータをみたり、データベースの削除などが可能です。
しかし、テーブルやデータ作成のSQLは--localをつけて実行していたので、
こちらには反映されていません。

production環境にデータを反映させるには、--localオプションをつけずに
d1 executeコマンドを実行すればOKです。

WorkersからD1にアクセス

生成されたindex.tsからD1にアクセスしてみます。
env.DBで作成したD1にアクセスできるので、
下記のように修正します。

export default {
	async fetch(request, env) {
	  const { pathname } = new URL(request.url);
	  console.log(env.DB);
  
	  if (pathname === "/api/users") {
		const { results } = await env.DB.prepare(
		  "SELECT * FROM Users WHERE age > ?"
		)
		  .bind(30)
		  .all();
		return Response.json(results);
	  }
	  // …
	  return new Response("Call /api/users to display users over 30 years old");
	},
  };

では、ローカルで試してみましょう。
ローカルで動かすにはlocalとpersistのオプションをつける必要があります。  

 % wrangler dev --local --persist
 ⛅️ wrangler 0.0.0-b918fc06 (update available 0.0.0-c725ce01)
-----------------------------------------------------------------------
Your worker has access to the following bindings:
- D1 Databases:
  - DB: my-d1 (xxxxxxxx)
⎔ Starting a local server...
- http://127.0.0.1:8787
BetaDatabase {}

もしここでno such tableエラーが出た場合、
better-sqlite3をインストールする必要があるかもしれません。

% npm install --save-dev better-sqlite3@7.6.2

/api/usersにアクセスすると、D1から取得したデータが表示されます。

% curl http://127.0.0.1:8787/api/users
[{"id":3,"name":"Hanako","age":35},{"id":5,"name":"Tom","age":40}]

デプロイ

Cloudflareのproduction環境にデプロイするのは簡単です。
先程実行したテーブル作成/データ登録SQLを--localなしで実行します。

% wrangler d1 execute my-d1 --file=./schema.sql

publishでデプロイすれば、
production用URLにアクセスできます。

% wrangler publish
・
・
% curl https://<Your Workers URL>/api/users
[{"age":35,"id":3,"name":"Hanako"},{"age":40,"id":5,"name":"Tom"}]

Summary

Cloudflare D1を試してみました。
すでにd1-ormd1-consoleといった、
関連するライブラリやツールも登場してきています。  

まだベータ前の段階ですが、リリースがとても楽しみです。

References