LoginSignup
2
1

More than 1 year has passed since last update.

SvelteKitでPostgresSQLへデータの登録・取得をしてみる

Last updated at Posted at 2023-01-18

はじめに

SvelteKitは公式ドキュメントが(体感)読みやすいですね!
しかし、公式ドキュメントではDBを利用するにはどうすればいいのかが、
ふんわりとしか書かれていないため、実際に理解のためにSvelteKitからDB接続を試してみたいと思います。
個人的に理解した内容になるため、誤りやもっと良い方法などがあればコメント頂けると嬉しいです。

前提

  • 開発環境:Windwos10
  • 主なバージョン
    • SvelteKit:1.0.0
    • Node.js:v16.16.0
    • Postgresql:PostgreSQL 12.2, compiled by Visual C++ build 1914, 64-bit

Postgresqlの準備

今回はDBに特にこだわりがなかったため、PostgreSQLを使用しました。
ローカル開発環境用にインストールする場合、次の記事が参考になると思われます。

SvelteKitの準備

公式ドキュメントに従って、SvelteKitのプロジェクトを作成します。

フロント画面の作成

今回は簡単なデータの登録・取得を試したいため、ふりかえりを記録できるアプリを作りたいと思います。
画面には、入力欄と入力結果一覧を表示させます。
画面の動きとしては、入力欄に入力した内容をDBに登録し、入力結果一覧をDBから取得していきます。

image.png

データの取得

なにかしらのデータをDBから取得して、画面上で使用したい場合は、まず「+page.svelte」にdata変数を定義します。

+page.svelte
<script lang='ts'>
    import LookBackList from '$lib/component/LookBackList.svelte'
    import type { PageData } from './$types';
    export let data: PageData;
</script>

そして、DBから値を取得するには、load関数をexportする「+page.server.ts」ファイルを作成します。
このload関数の返り値が、「+page.svelte」のdata変数に格納されます。

+page.server.ts
import type { PageServerLoad } from './$types';
import { getAllFromKptTable } from '$lib/server/db';

export const load = ( async () => {
    // DBから値を取得
    const allLookBack = await getAllFromKptTable();
    // 取得結果を整形して返却
    const keeps = allLookBack.filter((lookBack: any) => lookBack.type === 'Keep');
    const problems = allLookBack.filter((lookBack: any) => lookBack.type === 'Problem');
    const trys = allLookBack.filter((lookBack: any) => lookBack.type === 'Try');
    return {
        LookBacks: {
            keepLookBacks: keeps,
            problemLookBacks: problems,
            tryLookBacks: trys,
        },
    }
}) satisfies PageServerLoad;

DBからの値の取得には「node-postgres」というライブラリを使用します。
「src/lib/server/db.ts」ファイルを作成し、次のように修正します。

db.ts
import pg from 'pg';

export const initDataBaseConnect = () => {
    return new pg.Client({
        database: "hoge", // データベース名
        user: "hoge",     // ユーザー名
        password: "hoge", // パスワード
        host: "127.0.0.1",
        port: 5432,
    });
}

export const getAllFromKptTable = async () => {
    const pgClient = initDataBaseConnect();
    await pgClient.connect();
    const result = await pgClient.query(`SELECT * FROM kpt`);
    await pgClient.end()
    return result.rows;
}

「node-postgres」の使用方法については、以下のサイトを参考にしました。

ここまでの修正でDBから値を取得することができます。動作を確認してみましょう。
pgAdminを使用して、データを登録します。

INSERT INTO kpt VALUES ('Keep', 'Keepテスト', '001'), ('Problem', 'Problemテスト', '002'), ('Try', 'Tryテスト', '003');

image.png

画面にてデータが正しく取得できるか確認してみます。完璧ですね!

image.png

データの登録

次に画面上でユーザが入力した値を使って、DBにデータの登録を試してみます。
画面上の「add」ボタンを押下するとリクエストが飛ぶように修正します。

SendText.svelte
<script lang='ts'>
    // import分や変数定義、その他処理は省略...

    const sendInputText = () => {
        if (inputText.length > 0) {
            const param = {
                'lookBack': inputText,
                'lookBackType': lookBackType,
            };
            fetch(addLookBackUrl, {
                method: 'POST',
                body: JSON.stringify(param),
            }).then((res) => {
                inputText = '';
                dispatch('clickAddButton');
            })
        }
    }
</script>

<div>
    <input type='text' name='lookBack' bind:value={inputText} />
    <button on:click={sendInputText}>add</button>
</div>

リクエストに対応するサーバの処理を「src/routes/api/lookback/add/+server.ts」に記述していきます。
上記ファイルには、データの取得と同じ流れでDBに接続しますが、
DB接続用のClientのインスタンス生成については「src/hooks.server.ts」に記載し、インスタンスをevent.localsに格納します。
(必ずしもhooksでインスタンス生成する必要があるかは自信ないです。。。)

src/hooks.server.ts
import type { Handle } from '@sveltejs/kit';
import { initDataBaseConnect } from '$lib/server/db'
 
export const handle = (async ({event, resolve}) => {
    event.locals.db = initDataBaseConnect();
 
    const response = await resolve(event);
    return response;
}) satisfies Handle;
src/routes/api/lookback/add/+server.ts
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "./$types";
import uuid from 'uuid';

export const POST = (async ({locals, request}) => {
    const data = await request.json();
    const newId = uuid.v4();
    await locals.db.connect();
    await locals.db.query(`INSERT INTO kpt(id, type, lookback) VALUES('${newId}', '${data.lookBackType}', '${data.lookBack}')`);
    await locals.db.end();
    return json({});
}) satisfies RequestHandler;

hooks.server.tsとは、リクエストの処理である「+server.ts」の処理の前に行うインターセプターみたいなものと理解しています。
詳しくは、公式ドキュメントを参照してください。

これでDBへのデータ追加の処理が完成したため、動作を確認してみます。上手くいきました!
image.png
image.png

最終的なフォルダ構成

今回作成したプロジェクトのsrc配下のフォルダ構成は次の通りになりました。

src
 ├─lib
 │  ├─component               // コンポーネントの配置ディレクトリ
 │  │ ├─ LookBackList.svelte
 │  │ └─ SendText.svelte
 │  ├─images
 │  ├─server
 │  │ └─ db.ts                // DBの初期化処理を定義
 │  └─typescript
 ├─routes
 │  ├─api
 │  │ └─lookback
 │  │   ├─add
 │  │   │ └─ +server.ts       // レコード登録のAPI処理
 │  │   └─getByType
 │  │     └─ +server.ts       // Type別レコード取得のAPI処理
 │  ├─ +page.server.ts        // レンダリング前のデータ取得処理定義
 │  ├─ +page.svelte           // 画面定義
 │  └─ style.css
 └─ hooks.server.ts            // hook処理の定義

まとめ

躓く箇所もあったりしましたが、無事にSvelteKitからDB接続をすることができて良かったです。
ドキュメントを読むだけでなく、手を動かすのがやはり勉強になりますね。

参考文献

2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1