Indexed Database API は、Cookie, Web Storage, Web SQLデータベース と同様、アプリケーションデータをクライアント側に保存する仕組みのひとつです。下記の仕様が公開されています。
Cookie や Web Storage が Key-Value形式、Web SQLデータベースが SQL をサポートするのに対し、Indexed Database API では、SQLに依存しない NoSQL に分類される方法でデータにアクセスします。
Web SQLデータベースに代わり、今後の標準となる予定ですが、まだ仕様は確定しておらず、各ブラウザの実装にも非互換性がずいぶんあるようです。
Indexed Database API は、下記のブラウザで部分的にサポートが始まっています。
サンプルでは、DBの作成、データの追加、データの1件参照、データの全件参照、DBの削除を実装しています。Firefox 12, Chrome 19 で、動作を確認しています。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Indexed Database API Sample</title> <style> #message { margin: 1em; padding: 1em; border: 1px solid gray; font: 9pt Courier; white-space: pre; } </style> <script> var ver = 201205201; var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB; var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.mozIDBTransaction; var db = null; function print(msg) { document.getElementById("message").innerHTML += msg + "\n"; } function clearConsole() { document.getElementById("message").innerHTML = ""; } function createSample() { print("----------------------------------------------------"); print("START: createSample()"); var reqOpen = indexedDB.open("sampleDB", ver); reqOpen.onupgradeneeded = function(e) { print("START: reqOpen.onupgradeneeded()"); db = reqOpen.result; db.createObjectStore("sample", { "keyPath": "id" }); print("EXEC : createObjectStore()"); print("END : reqOpen.onupgradeneeded()"); } reqOpen.onsuccess = function(e) { print("START: reqOpen.onsuccess()"); db = reqOpen.result; if (db.setVersion) { var reqVersion = db.setVersion(ver); reqVersion.onsuccess = function() { print("START: reqVersion.onsuccess()"); db.createObjectStore("sample", { "keyPath": "id" }); print("EXEC : createObjectStore()"); print("END : reqVersion.onsuccess()"); } } print("END : reqOpen.onsuccess()"); } reqOpen.onerror = function(err) { print("ERROR: " + err.code + ":" + err.message); } reqOpen.onblocked = function(err) { print("INFO : BLOCKED"); } print("END : createSample()"); } function addSample() { print("----------------------------------------------------"); print("START: addSample()"); var userList = [ { "id": 1, "name": "Yamada", "age": 18, "addr": "Tokyo" }, { "id": 2, "name": "Suzuki", "age": 27, "addr": "Osaka" }, { "id": 3, "name": "Tanaka", "age": 36, "addr": "Kyoto" }, { "id": 4, "name": "Kimura", "age": 45, "addr": "Aichi" } ]; var transaction = db.transaction(["sample"], IDBTransaction.READ_WRITE); var store = transaction.objectStore("sample"); for (var i = 0; i < userList.length; i++) { var data = userList[i]; var reqAdd = store.add(data); print("EXEC : add() " + data.id + " / " + data.name + " / " + data.age + " / " + data.addr); reqAdd.onsuccess = function(e) { print("INFO : add() -> SUCCESS"); } reqAdd.onerror = function(e) { print("INFO : add() -> ERROR"); } } print("END : addSample()"); } function getSample() { print("----------------------------------------------------"); print("START: getSample()"); var transaction = db.transaction(["sample"], IDBTransaction.READ_ONLY); var reqGet = transaction.objectStore("sample").get(1); print("EXEC : get()"); reqGet.onsuccess = function(e) { var data = reqGet.result; print("DATA : " + data.id + " / " + data.name + " / " + data.age + " / " + data.addr); } reqGet.onerror = function(e) { print("ERROR: add() -> " + e); } print("END : getSample()"); } function getAllSample() { print("----------------------------------------------------"); print("START: getAllSample()"); var transaction = db.transaction(["sample"], IDBTransaction.READ_ONLY); var reqGet = transaction.objectStore("sample").openCursor(); print("EXEC : openCursor()"); reqGet.onsuccess = function(e) { var cursor = reqGet.result; var data = cursor.value; print("DATA : " + cursor.key + " / " + data.name + " / " + data.age + " / " + data.addr); cursor.continue(); } reqGet.onerror = function(e) { print("ERROR: add() -> " + e); } print("END : getAllSample()"); } function deleteSample() { print("----------------------------------------------------"); print("START: deleteSample()"); if (db) { db.close(); } var reqDelete = indexedDB.deleteDatabase("sampleDB"); print("EXEC : deleteDatabase()"); reqDelete.onsuccess = function(e) { print("INFO : deleteDatabase() -> SUCCESS"); } reqDelete.onerror = function(e) { print("ERROR: deleteDatabase() -> " + e); } reqDelete.onblocked = function(e) { print("INFO : BLOCKED"); } print("END : deleteSample()"); } </script> </head> <body> <button onclick="createSample()">CREATE</button> <button onclick="addSample()">ADD</button> <button onclick="getSample()">GET</button> <button onclick="getAllSample()">GET ALL</button> <button onclick="deleteSample()">DELETE</button> <button onclick="clearConsole()">CLEAR</button> <div id="message"></div> </body> </html>
まだ仕様が確定していないため、Firefox では mozIndexedDB, Chrome では webkitIndexedDB として実装しています。
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB; var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.mozIDBTransaction;
まず、データベースを開きます。第一引数にはデータベース名を指定します。第二引数は、2010年8月の仕様ではDBの説明を指定していました。2011年4月の仕様では第二引数は廃止されました。最新の 2011年12月の仕様では、第二引数は unsigned long long 型のバージョン(省略可能)を指定します。
reqOpen = indexedDB.open("sampleDB", 20120520);
Firefox 12 の実装では、reqOpen.onupgradeneeded イベントハンドラで createObjectStore() を呼び出します。Chrome 19 の実装では、reqOpen.onsuccess イベントハンドラで db.setVersion() を呼び出し、その reqVersion.onsuccess イベントハンドラで createObjectStore() を呼び出します。createObjectStore() の第一引数にはオブジェクトストア名を、第二引数にはキー名などを指定します。
// Firefox 12 reqOpen.onupgradeneeded = function(e) { db = reqOpen.result; db.createObjectStore("sample", { "keyPath": "id" }); } // Chrome 19 reqOpen.onsuccess = function(e) { db = reqOpen.result; var reqVersion = db.setVersion(ver); reqVersion.onsuccess = function() { db.createObjectStore("sample", { "keyPath": "id" }); } }
db.transaction() でトランザクションを生成し、transaction.objectStore() でオブジェクトストアを得た後、add() でデータを追加します。成功時には onsuccess, 失敗時には onerror イベントが発生します。
var data = { "id": 1, "name": "Yamada", "age": 18, "addr": "Tokyo" }; var transaction = db.transaction(["sample"], IDBTransaction.READ_WRITE); var store = transaction.objectStore("sample"); var reqAdd = store.add(data); reqAdd.onsuccess = function(e) { ... }; reqAdd.onerror = function(e) { ... };
データを検索するには get() を用います。引数にはキー値を指定します。結果は onsuccess ハンドラで参照します。
var transaction = db.transaction(["sample"], IDBTransaction.READ_ONLY); var store = transaction.objectStore("sample"); var reqGet = store.get(1); reqGet.onsuccess = function(e) { var data = reqGet.result; print("DATA : " + data.id + " / " + data.name + " / " + data.age + " / " + data.addr); }
データの一覧を得るには openCursor() を使用します。古い仕様では getAll() メソッドが用意されていましたが、廃止されました。
var transaction = db.transaction(["sample"], IDBTransaction.READ_ONLY); var store = transaction.objectStore("sample"); var reqGet = store.openCursor(); reqGet.onsuccess = function(e) { var cursor = reqGet.result; var key = cursor.key; var value = cursor.value; print("DATA : " + key + " / " + value.name + " / " + value.age + " / " + value.addr); cursor.continue(); }
データベースを削除するには deleteDatabase() を用います。
var reqDelete = indexedDB.deleteDatabase("sampleDB"); reqDelete.onsuccess = function(e) { ... }; reqDelete.onerror = function(e) { ... }; reqDelete.onblocked = function(e) { ... };