DatabaseIndexedDB

Dexie.jsを使ってIndexedDBを触ってみる

Dexieとは

JavaScriptでIndexedDBを使いやすくするライブラリのこと。

IndexedDBとはクライアント側でデータベースを使用するためのAPIであり、これを簡単に扱えるのが今回使うDexie.jsになる。

セットアップ

VueとかReactにも組み込めるみたいだけど今回はお試しなので、CDN形式で作ってみる。

htmlに以下を加える

<script src="<https://unpkg.com/dexie/dist/dexie.js>"></script>

Dexieを使用したIndexedDBの基本操作

チュートリアルを参考に今回は、データベースにFriendDatabase、テーブルにfriendsを作ってみる。

ここではテーブルといっているが、IndexedDB的にはオブジェクトストアというみたい。

データベースの作成

const db = new Dexie("FriendDatabase");

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

主キーに “id” とプロパティ “name” と “age” へのインデックスをもつfriendsテーブルを作る。

一つ目に指定したものが主キーになるみたい。

db.version(1).stores({
  friends: `
  id,
  name,
  age`,
});

オブジェクトストアの定義を変える場合には今設定しているバージョン1より大きい数を指定しないとストアを更新できないみたい。

あと、スキーマ構文というものもあるみたい。

構文意味
++自動インクリメントされる主キー
&一意のインデックス
*複数エントリのインデックス
[A+B]複合インデックスまたは主キー

++idとかにしたらデータ追加時には自動でインクリメントされた値が格納される。

レコードの追加、取得、更新、削除

IndexedDB的にはオブジェクトを操作する

追加

addは重複する主キーが既に登録されているとエラーが発生するが、putはオブジェクトを上書きする

// add
await db.friends.add({ id: 1, name: "Josephine", age: 21 });

// put
await db.friends.put({ id: 1, name: "Josephine", age: 21 });

// bulkPut
await db.friends.bulkPut([
  { id: 1, name: "Josephine", age: 21 },
  { id: 2, name: "Per", age: 75 },
  { id: 3, name: "Simon", age: 5 },
  { id: 4, name: "Sara", age: 50, notIndexedProperty: "foo" },
]);

取得

// 全件検索
const allFriends = await db.friends.toArray();

// where: ageが0~25のオブジェクトを検索
const filterdAgeFriends = await db.friends
  .where("age")
  .between(0, 25)
  .toArray();

// orferBy: 年齢で降順
const orderdFriends = await db.friends.orderBy("age").reverse().toArray();

// startsWith; nameが"S"で始まるオブジェクトを検索
const filterdNameFriends = await db.friends
  .where("name")
  .startsWith("S")
  .toArray();

更新

// id(key)が2のレコードのnameを "Ashitaka" に変更
db.friends.update(2, {name: "Ashitaka"})

削除

// id(key)が2のレコードを削除
db.friends.delete(2)

トランザクション

Dexieを使えばIndexedDBでもトランザクション制御をすることができる

トランザクションを開始するには 、transaction() メソッドを使用する。

try {
  await db.transaction("rw", db.friends, async () => {
    await db.friends.add({ id: 1, name: "Josephine", age: 21 });
    await db.friends.add({ id: 2, name: "Per", age: 75 });
    await db.friends.add({ id: 1, name: "Josephine", age: 21 }); // ←主キー重複エラー
  });
} catch (error) {
  console.error("An error occurred:", error);
}

この例だと主キーであるidの1が重複して追加されてしまうため、3つめの追加時にエラーが発生しロールバックされ結果的に何もデータは登録されない