🐳

IndexedDB触ってみた

2023/09/18に公開

ブラウザでもDB操作できます?
お試しも兼ねて備忘します

IndexedDBという名のデータベース

ブラウザに搭載されているDBなんだな、LocalStorageやSessionStorageなどのWeb Storage APIと同じ様にブラウザにデータを保存できる仕組み

特徴

  • オンライン・オフライン
  • 同一オリジンポリシー
  • キーと値の組を格納 ("age": 44 みたな)
  • トランザクションデータベースモデル
  • 非同期
  • SQLを使用しない(select * from user ← ☓)

https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API/Basic_Terminology

早速試してみる

IndexedDBを操作するHTMLを作成してみました
こちらを使って試してみます

IndexedDB作成のHTML
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Indexeddb test</title>
</head>
<body>
    <h1>IndexedDBのテスト</h1>
    <div style="margin-bottom: 10px;"><button type="button" onclick="indexeddb_create();">IndexedDBの作成</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_object_store_create();">IndexedDBにオブジェクトストアを作成</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_insert_data();">IndexedDBにデータを作成</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_select_data();">IndexedDBのデータを検索</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_update_data();">IndexedDBのデータを更新</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_select_data();">IndexedDBのデータを検索</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_delete_data();">IndexedDBのデータを削除</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_select_data();">IndexedDBのデータを検索</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_object_store_delete();">IndexedDBのオブジェクトストアを削除</button></div>
    <div style="margin-bottom: 10px;"></div><button type="button" onclick="indexeddb_delete();">IndexedDBの削除</button></div>
    <hr>
    <p>実行結果</p>
    <p id="success"></p>
    <hr>
    <p style="color: #FF0000;">エラーが発生した場合</p>
    <p id="error"></p>
    <script>
        const db_name = "MyTestDatabase";
        const db_base_version = 1;
        const db_object_store_create_version = 2;
        const db_object_store_delete_version = 3;
        const store_name = "customer";
        const err = document.getElementById("error");
        const success = document.getElementById("success");
        const default_data = {id: '#12345#user_id', name: 'test taro'};

        // indexeddb 作成
        function indexeddb_create(){
            const createRequest = window.indexedDB.open(db_name, db_base_version);

            createRequest.onerror = (event) => {
                err.innerHTML = event.target.error;
            };
            createRequest.onsuccess = (event) => {
                db = event.target.result;
                success.innerHTML = `${db_name}を作成しました。作成したバージョン = ${event.target.result.version}`;
                // 接続を解除
                db.close();
            }
        }

        // object store 作成
        function indexeddb_object_store_create(){
            const openRequest = window.indexedDB.open(db_name, db_object_store_create_version);

            openRequest.onupgradeneeded = (event) => {
                const db = event.target.result;
                // 顧客の情報を保存する objectStore を作成します
                const objectStore = db.createObjectStore(store_name, { keyPath: "id" });
                success.innerHTML = `${db_name}${store_name}を作成しました。`;
                // 接続を解除
                db.close();
            };
        }

        // insert データ
        function indexeddb_insert_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name, 'readwrite').objectStore(store_name);
                customerObjectStore.add(default_data);
                success.innerHTML = `${db_name}${store_name}${default_data.id}を追加しました。`;
                // 接続を解除
                db.close();
            };
        }

        // update データ
        function indexeddb_update_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                default_data.name = 'テスト二郎';
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name, 'readwrite').objectStore(store_name);
                customerObjectStore.put(default_data);
                success.innerHTML = `${db_name}${store_name}${default_data.id}を更新しました。`;
                // 接続を解除
                db.close();
            };
        }

        // delete データ
        function indexeddb_delete_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name, 'readwrite').objectStore(store_name);
                customerObjectStore.delete(default_data.id);
                success.innerHTML = `${db_name}${store_name}${default_data.id}を削除しました。`;
                // 接続を解除
                db.close();
            };
        }

        // select
        function indexeddb_select_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name).objectStore(store_name);
                const get_result = customerObjectStore.get(default_data.id);

                get_result.onerror = (event) => {
                    err.innerHTML = event.target.error;
                }
                get_result.onsuccess = (event) => {
                    if (typeof get_result.result === 'undefined') {
                        success.innerHTML = `${db_name}${store_name}からデータを取得できません`;
                    }
                    else {
                        success.innerHTML = `${db_name}${store_name}からid:${get_result.result.id},name:${get_result.result.name}が見つかりました。`;
                    }
                }
                // 接続を解除
                db.close();
            };
        }

        // object store 削除
        function indexeddb_object_store_delete(){
            const openRequest = window.indexedDB.open(db_name, db_object_store_delete_version);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onupgradeneeded = (event) => {
                const db = event.target.result;
                //objectStoreを削除します
                const objectStoreDelete = db.deleteObjectStore(store_name);
                success.innerHTML = `${db_name}${store_name}を削除しました。`;
            };
        }

        // indexeddb 削除
        function indexeddb_delete(){
            const createRequest = window.indexedDB.deleteDatabase(db_name);
            success.innerHTML = `${db_name}を削除しました。`;
        }

    </script>
</body>
</html>

※ブラウザの開発者モードを開いておいてください、私はChromeを使用しています
※サンプルソースを掲載していますが、不完全です。特にエラー処理関係を省いていますのでご承知願います

データベース作成

まずはデータベースを作成します
「IndexedDBの作成」ボタンを押すとデータベースが作成されます

ストレージ欄のIndexedDB欄にMyTestDatabaseが作成されました。
※データベースはMySQLやPosgre等のDatabaseとほぼ同じ概念と理解しています。

javascriptは以下となります

        // indexeddb 作成
        function indexeddb_create(){
            const createRequest = window.indexedDB.open(db_name, db_base_version);

            createRequest.onerror = (event) => {
                err.innerHTML = event.target.error;
            };
            createRequest.onsuccess = (event) => {
                db = event.target.result;
                success.innerHTML = `${db_name}を作成しました。作成したバージョン = ${event.target.result.version}`;
                // 接続を解除
                db.close();
            }
        }

オブジェクトストアの作成

オブジェクトストアを作成します
「IndexedDBにオブジェクトストアを作成」ボタンを押すとオブジェクトストアが作成されます

MyTestDatabaseの配下にcustomerオブジェクトストアが作成されました。
※オブジェクトストアはMySQLやPosgre等のtableとほぼ同じ概念と理解しています。

javascriptは以下となります

        // object store 作成
        function indexeddb_object_store_create(){
            const openRequest = window.indexedDB.open(db_name, db_object_store_create_version);

            openRequest.onupgradeneeded = (event) => {
                const db = event.target.result;
                // 顧客の情報を保存する objectStore を作成します
                const objectStore = db.createObjectStore(store_name, { keyPath: "id" });
                success.innerHTML = `${db_name}${store_name}を作成しました。`;
                // 接続を解除
                db.close();
            };
        }

データの登録

オブジェクトストアにデータを登録します
「IndexedDBにデータを作成」ボタンを押すとcustomerオブジェクトストアにデータが登録されます
※今回は固定のデータを用意しています。本来は入力値やAPI等で取得したデータを登録するはずです

customerオブジェクトストアが作成されました。
※データが最新でない可能性があります。と、開発者モードで警告されます。その際は開発者モード側の更新アイコンをクリックしてください

javascriptは以下となります

        // insert データ
        function indexeddb_insert_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name, 'readwrite').objectStore(store_name);
                customerObjectStore.add(default_data);
                success.innerHTML = `${db_name}${store_name}${default_data.id}を追加しました。`;
                // 接続を解除
                db.close();
            };
        }

データの検索

オブジェクトストアのデータを検索します
「IndexedDBのデータを検索」ボタンを押すとcustomerオブジェクトストア登録されているデータを取得できます

javascriptは以下となります

        // select
        function indexeddb_select_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name).objectStore(store_name);
                const get_result = customerObjectStore.get(default_data.id);

                get_result.onerror = (event) => {
                    err.innerHTML = event.target.error;
                }
                get_result.onsuccess = (event) => {
                    if (typeof get_result.result === 'undefined') {
                        success.innerHTML = `${db_name}${store_name}からデータを取得できません`;
                    }
                    else {
                        success.innerHTML = `${db_name}${store_name}からid:${get_result.result.id},name:${get_result.result.name}が見つかりました。`;
                    }
                }
                // 接続を解除
                db.close();
            };
        }

データの更新

オブジェクトストアのデータを更新します
「IndexedDBのデータを更新」ボタンを押すとcustomerオブジェクトストアのデータが更新されます

ちゃんと更新されたか確認します。IndexedDBのデータを検索でデータを確認しましょう、nameが「test taro」→「テスト二郎」に変更されているはずです

javascriptは以下となります

        // update データ
        function indexeddb_update_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                default_data.name = 'テスト二郎';
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name, 'readwrite').objectStore(store_name);
                customerObjectStore.put(default_data);
                success.innerHTML = `${db_name}${store_name}${default_data.id}を更新しました。`;
                // 接続を解除
                db.close();
            };
        }

データの削除

オブジェクトストアのデータを削除します
「IndexedDBのデータを削除」ボタンを押すとcustomerオブジェクトストアのデータが削除されます

ちゃんと削除されたか確認します。IndexedDBのデータを検索でデータを確認しましょう、データが削除されたので「MyTestDatabaseのcustomerからデータを取得できません」と表示されます

javascriptは以下となります

        // delete データ
        function indexeddb_delete_data(){
            const openRequest = window.indexedDB.open(db_name);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onsuccess = (event) => {
                const db = event.target.result;
                const customerObjectStore = db.transaction(store_name, 'readwrite').objectStore(store_name);
                customerObjectStore.delete(default_data.id);
                success.innerHTML = `${db_name}${store_name}${default_data.id}を削除しました。`;
                // 接続を解除
                db.close();
            };
        }

オブジェクトストアの削除

オブジェクトストアを削除します
「IndexedDBのオブジェクトストアを削除」ボタンを押すとcustomerオブジェクトストアが削除されます

MyTestDatabase配下からcustomerオブジェクトストアが削除されました

javascriptは以下となります

        // object store 削除
        function indexeddb_object_store_delete(){
            const openRequest = window.indexedDB.open(db_name, db_object_store_delete_version);

            openRequest.onerror = (event) => {
                console.log("error");
                err.innerHTML = event.target.error;
            };
            openRequest.onupgradeneeded = (event) => {
                const db = event.target.result;
                //objectStoreを削除します
                const objectStoreDelete = db.deleteObjectStore(store_name);
                success.innerHTML = `${db_name}${store_name}を削除しました。`;
            };
        }

データベースの削除

データベースを削除します
「IndexedDBの削除」ボタンを押すとデータベースが削除されます

MyTestDatabase配下からcustomerオブジェクトストアが削除されました
※ボタンを押した後、データベースは削除されるのですが、開発者モードから消えませんw
 ブラウザ更新すると削除されていますのでご安心ください

javascriptは以下となります

        // indexeddb 削除
        function indexeddb_delete(){
            const createRequest = window.indexedDB.deleteDatabase(db_name);
            success.innerHTML = `${db_name}を削除しました。`;
        }

振り返り

今回はIndexedDBを触ってみました
今までDBはバックエンドの専用ミドルだと思っていましたがフロントでもDBを立ち上げてデータ管理することができました
※ITって改めてすごい
ただ、使い方や勘どころ、セキュリティやベンチマーク等、まだまだ知らない事が多いです
今後少しずつでも触りながら勉強しています
※同一オリジンポリシーというものの、iframeでIndexedDBのページを読み込んでDBに登録されているデータとか読み込めちゃうのかな。。。

この記事が少しでも役立つ情報を提供できましたら幸いです。
読んでくださった皆様に心から感謝申し上げます

Discussion