開発者ブログ
HTML5資料室 » IndexedDB概要

IndexedDB概要

Last modified by masaru-yokoyama on 2014/05/16, 14:36

Indexed Database APIとは

JavaScriptを使用してデータを管理できるキー/バリュー型のオブジェクト指向データベース。

サポート状況

デスクトップブラウザ

ブラウザ  Chrome  Firefox  Internet Explorer  Opera  Safari 
バージョン  12.0(webkit)~  4.0(moz)~
 16.0~ 
 10.0(ms)  ×  ×

モバイルブラウザ

ブラウザ  Mobile Safari  Opera Mini  Opera Mobile  Android Browser  Blackberry Browser  Chrome for Android  Firefox for Android 
バージョン  ×  ×  ×  ×  10(webkit)~  18.0(webkit)~  15.0(moz)~ 

※括弧はプレフィックス付でのサポートを表す。

使用方法

データベースへの接続

IDBFactory.open()にデータベース名を指定して実行することで接続できる。

   var idb = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
    idb.open('databasename');

バージョンの更新

Chrome22とFirefox16で実装に差異がある。詳細については動作検証-バージョン更新を参照。
※ Firefox16の実装のほうが、W3Cの仕様に準拠している。

オブジェクトストアの作成・削除

オブジェクトストアの作成・削除は、バージョン更新のコールバック内でしか行うことができない。

オブジェクトストアの作成  IDBDatabase.createObjectStore(String databaseName, Object parameter)
オブジェクトストアの削除  IDBDatabase.deleteObjectStore(String databaseName)

Chrome22とFirefox16で実装方法が異なる。
※ Firefox16の実装のほうが、W3Cの仕様に準拠している。

Chrome22

onsuccessコールバック内で、オブジェクトストアの作成・削除が実行できる。

    var req = window.webkitIndexedDB.open('db1');

     req.onsuccess = function(ev) {
        var db = this.result;

        var verReq = db.setVersion('2');

         verReq.onsuccess = function(ev) {
            var tx = this.result;
            var db = tx.db;
            
            // userという名前のオブジェクトストアを作成
            var store = db.createObjectStore('user', {
                 keyPath: "name",
                 autoIncrement: false
             });

            // userという名前のオブジェクトストアを削除
            db.deleteObjectStore('user');
         };
     };

Firefox16

onupgradeneededコールバック内で、オブジェクトストアの生成・削除が実行できる。

   var req = window.indexedDB.open('db1', parseInt(VERSION));

   // open()で指定されたバージョンの値が、既存のバージョンの値と異なる場合に発生するイベント
   req.onupgradeneeded = function(ev) {
       var db = this.result;
       var store = db.createObjectStore('user', {
            keyPath: "name",
            autoIncrement: false
        });

        db.deleteObjectStore('user');
    };

in-line key と out-of-line key

キーには、オブジェクトストア内にキーが存在するin-line keyと、オブジェクトストアの外にキーが存在するout-of-line keyの二種類あります。
上記サンプルはin-line keyでオブジェクトストアを作成しています。

上記サンプル以外にも、以下のような実装でキーを指定できます。

in-line key

keyPathを指定せずautoIncrementはtrueでオブジェクトストアを生成すると、キーはインクリメントで自動生成される。

   var store = db.createObjectStore('user', {
        autoIncrement: true
    });

out-of-line key
keyPathを指定せずautoIncrementはfalseでオブジェクトストアを生成すると、add()やput()でデータを追加するとき第二引数にキー値を指定しなければならない。

   var store = db.createObjectStore('user', {
        autoIncrement: false
    });

インデックスの作成・削除

インデックスの作成・削除もオブジェクトストアの作成・削除と同じく、バージョン更新のコールバック内しか行うことができない。

インデックスの作成  IDBDatabase.createIndex(String databaseName, String keyPath, Object parameter)
インデックスの削除  IDBDatabase.deleteIndex(databaseName)

Chrome22とFirefox16で実装方法が異なる。
※ Firefox16の実装のほうが、W3Cの仕様に準拠している。

Chrome22

onsuccessコールバック内で、インデックスの作成・削除が実行できる。

    var req = window.webkitIndexedDB.open('db1');

     req.onsuccess = function(ev) {
        var db = this.result;

        var verReq = db.setVersion('2');

         verReq.onsuccess = function(ev) {
            var tx = this.result;
            var store = tx.objectStore('address');
      
            // キーnameにインデックスを作成
            store.createIndex('name', 'name', {
                 unique: true
             });

            // インデックスnameを削除
            store.deleteIndex('name');
         };
     };

Firefox16

onupgradeneededコールバック内で、インデックスの作成・削除が実行できる。

   var req = window.indexedDB.open('db1', 2);

   // open()で指定されたバージョンの値が、既存のバージョンの値と異なる場合に発生するイベント
   req.onupgradeneeded = function(ev) {
       var tx = this.transaction;
       var store = tx.objectStore('user');
       
       // キーnameにインデックスを作成
       store.createIndex('name', 'name', {
           unique: true
        });

       // インデックスnameを削除
       store.deleteIndex('name');
    };

トランザクションの生成

トランザクションの生成は、IDBDatabase.transaction()を使用する。
トランザクションには、readonly(読み取り専用)、readwrite(読み書き可)、versionchange(バージョン更新)の3種類がある。

メソッド説明 
 transaction(String objectStoreName, String mode)  modeには"readonly"、"readwrite"、"versionchangetransaction"を指定する。
IDBTransaction.READ_ONLY、IDBTransaction.READ_WRITE、IDBTransaction.READ_ONLY、IDBTransaction.VERSION_CHANGEが用意されているで定数でも指定できる。
Number型の値(0,1,2)でも指定できるが非推奨とされている。
   var tx = db.transaction('user', 'readwrite');    

トランザクションが発生したメソッドの処理が終了すれば、トランザクションはコミットされる。
ロールバックしたい場合はabort()を実行する。

   // トランザクションの開始
   var tx = db.transaction('user', 'readwrite');
   // トランザクションを破棄(ロールバック)
   tx.abort();

トランザクションは自動的にコミットされるようになっている。
コミットされたかはoncompleteイベントの発生で、ロールバックされたかはonerrorイベントの発生で判定できる。
http://www.w3.org/TR/IndexedDB/#steps-for-committing-a-transaction

   // トランザクションの開始
   var tx = db.transaction('user', 'readwrite');
   
    tx.oncomplete = function() {
        alert('コミットが完了しました。');
    };

    tx.onerror = function() {
        alert('ロールバックされました。');
    };

データの追加

オブジェクトストアにデータを追加するには、IDBObjectStore.add()または、IDBObjectStore.put()を使用する。
put()もadd()も機能に違いは無い。

メソッド説明 
 add(Object data, Any key)  autoIncremetオプションをfalseでオブジェクトストアを生成した場合、dataにはオブジェクトストアのキーと同名のプロパティを持っていなければならない。
また、createObject()時にkeyPathを指定しなかった場合はkeyにキー値を指定しなければならない。

userオブジェクトストア(name, age, addressを持つ)に、レコードを1件登録する。

   var tx = db.transaction('user', 'readwrite');
   var store = tx.objectStore('user');
   var data = {
        name: 'suzuki',
        age: 20,
        address: 'tokyo'
    };

   var addReq = store.add(data);

    addReq.onsuccess = function() {
        alert('登録成功');
    };

    addReq.onerror = function() {
        alert('登録失敗');
    };

いくつかのパターンのオブジェクト構造を追加した場合の動作検証を行いました。 動作検証-データ追加

データの削除

オブジェクトストアからデータを削除するには、IDBObjectStore.delete()またはIDBObjectStore.clear()を使用する。

メソッド説明 
delete(String key)  指定されたキー名と一致するレコードを1件削除する。
clear()オブジェクトストアからレコードを全て削除する。

userオブジェクトストア(name, age, addressを持つ)から、nameが『suzuki』と一致するレコードを削除する。

   var tx = db.transaction('user', 'readwrite');
   var store = tx.objectStore('user');
   var delReq = store.delete('suzuki');

    delReq.onsuccess = function() {
        alert('全件削除成功');
    };

    delReq.onerror = function() {
        alert('全件削除失敗');
    };

userオブジェクトストア(name, age, addressを持つ)から、レコードを全件削除する。

   var tx = db.transaction('user', 'readwrite');
   var store = tx.objectStore('user');
   var delReq= store.clear();

    delReq.onsuccess = function() {
        alert('削除成功');
    };

    delReq.onerror = function() {
        alert('削除失敗');
    };

データの検索

1件取得する場合

データを1件取得したい場合は、IDBObjectStore.get()を使用する。

メソッド説明 
get(String key)キーの値と一致するレコードを取得する。複数件ヒットした場合は最初にヒットしたレコードを取得する。

userオブジェクトストア(name, age, addressを持つ)から、nameが『suzuki』と一致するレコードを取得する。

   var tx = db.transaction('user', 'readwrite');
   var store = tx.objectStore('user');
   var req = store.get('suzuki');

    req.onsuccess = function() {
       var result = this.result;
        console.log(result); //  {name: 'suzuki', age:20, address:'tokyo'}
   };

複数件取得する場合

データを複数件取得したい場合は、IDBObjectStore.openCursor()を使用する。

メソッド説明 
openCursor(IDBKeyRange range, Number direction)  rangeにはキーの検索範囲を指定し、directionには取得順序を指定する。
directionに指定する値は、IDBCursor.NEXT、IDBCursor.NEXT_NO_DUPLICATE、IDBCursor.PREV、IDBCursor.PREV_NO_DUPLICATE定数を使用する

userオブジェクトストア(name, age, addressを持つ)から、nameがaからzで始まるレコードを取得している。

   var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.mozIDBKeyRange;
   var tx = db.transaction('user', 'readwrite');
   var store = tx.objectStore('user');
   var range = IDBKeyRange.bound('a', 'z');
   var req = store.index('name').openCursor(range);
   var result = [];

    req.onsuccess = function() {
       var cursor = this.result;

       if (cursor) {
            result.push(cursor.value);
            cursor.continue();
        }
    };

検索結果には、オブジェクトストアに追加したときの型で返ってくる。

レンジに英字を指定した場合(上記例では'a'~'z')、大文字小文字が区別される

カラムを検索条件として使用するためには、そのカラムをインデックスに設定しなければならない
上記サンプルコードでは、インデックスが設定されているnameカラムを、検索条件に使用している。

データの更新

データを複数件取得したい場合は、IDBCursor.update()を使用する。

メソッド説明 
update(Object data)引数に指定されたデータで、現在カーソルが指しているデータを更新する。

userオブジェクトストア(name, age, addressを持つ)から、nameが『suzuki』であるレコードのageを『30』に更新する。

   var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.mozIDBKeyRange;
   var tx = db.transaction('user', 'readwrite');
   var store = tx.objectStore('user');
   var range = IDBKeyRange.bound('a', 'z');
   var req = store.index('name').openCursor(range);
   var result = [];

    req.onsuccess = function() {
       var cursor = this.result;
       var data = cursor.value;

        data.age = 30;

       if (cursor) {
            cursor.update(data);
            cursor.continue();
        }
    };

API

IDBFactory

Indexed DBに接続するために必要なオブジェクト

メンバ戻り値説明ChromeFirefox
cmp(key1, key2)FunctionNumber引数に指定されたキーの大小を比較する。key1>key2なら1、key1<key2なら-1、key1=key2なら0を返す。
引数に指定できる型はキーに指定できる型と同く、String、Date、Float(Number)、Array型が指定できる。
deleteDatabase(name, version)FunctionIDBRequest指定された名前のデータベースを削除する。
open(name, version)FunctionIDBRequest指定された名前のデータベースに接続する。
第二引数を指定した場合はそのバージョンに更新する。ただしChrome22の場合は第二引数を指定できない。
webkitGetDatabaseNames×

IDBRequest(IDBOpenDBRequest)

データベースやオブジェクトストアへのアクセス結果を非同期で取得するためのオブジェクト

メンバ戻り値説明ChromeFirefox
resultAny問い合わせ結果を保持するプロパティ。例えばIDBFactory.oepn()を実行するとIDBDatabase型のオブジェクトが、IDBObjectStore.openCursor()を実行するとIDBCursorオブジェクトが入っている。
sourceIDBFactoryこのリクエストの要求元であるオブジェクトが格納される。
transactionIDBTransactionトランザクションオブジェクト
errorErrorエラーが発生した場合、エラー情報を持つオブジェクトが格納される。
readyStateStringリクエストの状態を文字列で表す。
onsuccessFunctionvoidこのプロパティにハンドラを設定すると、onsuccessイベントが発生したときにそのハンドラが実行される。
onerrorFunctionvoidこのプロパティにハンドラを設定すると、onerrorイベントが発生したときにそのハンドラが実行される。
onupgradeneededFunctionvoidこのプロパティにハンドラを設定すると、onupgradeneededイベントが発生したときにそのハンドラが実行される。×
onblockedFunctionvoidこのプロパティにハンドラを設定すると、onblockedイベントが発生したときにそのハンドラが実行される。×
webkitErrorMessage×
errorCodeNumberエラーが発生した場合、エラーコードが格納される。×

IDBDatabase

データベースを操作(オブジェクトストアの生成・削除、インデックスの生成・削除)するためのオブジェクト

メンバ戻り値説明ChromeFirefox
nameStringデータベース名
versionString/Numberデータベースのバージョンを表す。ChromeはString型、FirefoxはNumber型で値を保持している。
objectStoreNamesStringListこのデータベースが持つオブジェクトストアの名前をリストで持っている。
createObjectStore(name, optionalParameter)FunctionIDBObjectStoreオブジェクトストアを作成する。
deleteObjectStore(name)Functionvoidオブジェクトストアを削除する。
transactionFunctionIDBTransactionトランザクションを保持する。
closeFunctionvoidデータベースの接続を解除する。
setVersion(version)FunctionIDBRequest引数に指定した値でバージョンを更新する。×

IDBTransaction

IndexedDBで扱うトランザクションの種類を定義し、トランザクションを生成するためのオブジェクト

メンバ戻り値説明ChromeFirefox
modeStringトランザクションの種類を文字列で表す。"readonly", "versionchange", "readwrite"の三種類がある。
dbIDBDatabase現在接続しているデーターベースを操作するためのオブジェクト。IDBRequest.transactionやIDBObjectStore.transactionにこのプロパティが存在する。
window.IDBTransaction、window.webkitIDBTransaction、window.mozIDBTransactionにはこのプロパティは存在しない。
READ_ONLYStringトランザクションのモードを設定するときに使用する定数。Chromeでは0を、Firefoxでは"readonly"を返す。
READ_WRITEStringトランザクションのモードを設定するときに使用する定数。Chromeでは1を、Firefoxでは"readwrite"を返す。
VERSION_CHANGEStringトランザクションのモードを設定するときに使用する定数。Chromeでは2を、Firefoxでは"versionchange"を返す。
errorErrorエラーオブジェクト
objectstoreFunctionIDBObjectStore指定された名前のオブジェクトストアを取得する。
onabortFunctionvoidこのプロパティにハンドラを設定すると、onabortイベントが発生したときにそのハンドラが実行される。
oncompleteFunctionvoidこのプロパティにハンドラを設定すると、oncompleteイベントが発生したときにそのハンドラが実行される。
onerrorFunctionvoidこのプロパティにハンドラを設定すると、onerrorイベントが発生したときにそのハンドラが実行される。

IDBObjectStore

オブジェクトストアを操作(データの追加・削除、件数の取得)するためのオブジェクト

メンバ戻り値説明ChromeFirefox
autoIncrementBooleanautoIncrementオプションが有効かを表す。
indexNamesStringListインデックスの名前一覧をリストで持つ。
keyPathStringkeyPathオプションが有効かを表す。
nameStringオブジェクトストア名
transactionIDBTransactionトランザクションを持つ。
add(value)FunctionIDBRequest引数に指定されたデータを登録する。
put(value)FunctionIDBRequest引数に指定されたデータを登録する。
clear()FunctionIDBRequestオブジェクトストアに登録されているデータを全て削除する。
count()FunctionIDBRequestオブジェクトストアに登録されているデータを件数を返す。
createIndex(name, optionalParameter)FunctionIDBIndex このオブジェクトストアに指定された名前のインデックスを作成する。
get(key)FunctionIDBRequestデータを1件取得する。
indexFunctionIDBIndex指定された名前のインデックスを取得する。
openCursor(range, direction)FunctionIDBRequest指定されたインデックスの範囲のデータを取得する。

IDBKeyRange

レコードを検索する際、オブジェクトストアに設定されたインデックスの範囲を指定するためのオブジェクト

メンバ戻り値説明ChromeFirefox
bound(lower, upper)FunctionIDBKeyRange指定されたインデックスの範囲のキーレンジオブジェクトを生成する。
lowerBound(lower)FunctionIDBKeyRange下限値のみを指定してキーレンジオブジェクトを生成する。
only(value)FunctionIDBKeyRange特定のインデックス値を指定してキーレンジオブジェクトを生成する。
upperBound(upper)FunctionIDBKeyRange上限値のみを指定してキーレンジオブジェクトを生成する。

IDBCursor

カーソルを操作するためのオブジェクト

メンバ戻り値説明ChromeFirefox
NEXTNumberopenCursor()の第二引数に使用する、昇順でレコード取得するための定数。
Chromeは0をFirefoxは"next"を返す。
NEXT_NO_DUPLICATENumberopenCursor()の第二引数に使用する、昇順で重複無しでレコード取得するための定数。
Chromeは1をFirefoxは"nextunique"を返す。
PREVNumberopenCursor()の第二引数に使用する、降順でレコード取得するための定数。
Chromeは2をFirefoxは"prev"返す。
PREV_NO_DUPLICATENumberopenCursor()の第二引数に使用する、降順で重複無しでレコード取得するための定数。
Chromeは3をFirefoxは"prevunique"返す。
advance(count)FunctionBooleanカーソルのポジションを指定した位置にすすめる。
新しいカーソルを取得する前に2回以上このメソッドを実行するとエラーとなる。
また引数に指定する値は1より大きい値を指定する。
continue()FunctionBooleanカーソルのポジションを次の操作方向にすすめる。
delete()FunctionBoolean現在のカーソルが指しているレコードを削除する。
update(value)FunctionIDBRequest現在のカーソルが指しているレコードを更新する。

IDBIndex

インデックスを操作するためのオブジェクト

メンバ戻り値説明ChromeFirefox
nameStringインデックス名
objectStoreIDBObjectStoreオブジェクトストア
keyPathStringインデックスの対象となっているキー名
uniqueBooleanuniqueオプションが有効かを表す。
multiEntryBooleanmultiEntryオプションが有効かを表す。
count()FunctionIDBRequestこのインデックスが持つレコードの件数を取得する。
get(key)FunctionIDBRequest指定したキーと一致するレコードを取得する。
getKey(key)FunctionIDBRequestIDBObjectStore.get()のキー版。
キー名またはIDBRangeオブジェクトを指定する、とその条件に一致するデータのキーを取得する。
openCursor()FunctionIDBRequest指定されたインデックスの範囲のデータを取得する。
openKeyCursor()FunctionIDBRequest指定されたインデックスの範囲のデータのキーを取得する。

動作検証

バージョン更新

バージョンの更新方法に差異があるため次のように実装する必要がある。

Chrome22

IDBDatabase.setVersion()に、String型の値で設定する。

var idb = window.webkitIndexedDB;
var req = idb.open('hifive');
req.onsuccess = function() {
   var db = this.result; // db = IDBDatabaseオブジェクト
   db.setVersion("1.0");

Firefox16

IDBFactory.open()の第二引数に、Number型の値で設定する。

  • 指定した値の少数点以下は切り捨てられる。
  • 前回指定したバージョンの値よりも大きい値を指定しなければならない。指定しない場合はVersionErrorエラーが発生する。
var idb = window.indexedDB;
var req = idb.open('hifive', 1);

データ追加

循環参照のオブジェクトを保存した場合

addressカラムに以下の循環参照しているオブジェクトを保存し取り出す。

   var a = {};
    a.b = a;

仕様

オブジェクトストアにはオブジェクトを持つオブジェクトも保存することができ、循環参照が排除されたオブジェクトクローンが保存される。
http://www.w3.org/TR/IndexedDB/#widl-IDBObjectStoreSync-add-any-any-value-any-key

Chrome22

クローンはされているが循環参照が排除されず、直後に『maximum call stack size exceeded.』エラーが発生する。

circuler_ch.png

Firefox16

クローンはされているが循環参照が排除されず、直後にブラウザが固まってしまう。

circuler_ff.png

オブジェクトを持つオブジェクトを保存した場合

Chrome22

キー以外のカラムに対してのみ、オブジェクトを持つオブジェクトもテーブルに登録できる。

obj-in-obj_ch.png

Firefox 16

キー以外のカラムに対してのみ、オブジェクトを持つオブジェクトもテーブルに登録できる。

obj-in-obj_ff.png

様々な型のオブジェクトを保存した場合

仕様

キーに指定したカラムには、String、Date、Float(Number)、Array型の値しか保存することができない。
配列(Array)を指定した場合、配列の中身はString、Float(Number)またはDateでなければならない。
http://www.w3.org/TR/IndexedDB/#dfn-key-1

Chrome22

型名キーのカラムキー以外のカラム
null×
undefined×
Array
Number
String
Boolean×
RegExp×
Date
Object×
DOMElement××
Function××

Firefox16

型名キーのカラムキー以外のカラム
null×
undefined×
Array
Number
String
Boolean×
RegExp×
Date
Object×
DOMElement×××
Function××

データの検索

クエリ(WHEREやJOIN等)を実行できるか

Indexed Dataabse APIの機能ではRDBMSにあるWHEREやJOINといった複雑な条件指定ができない。
そのため、openCursor()でデータを取得し、結合や絞込みといった処理をJavaScriptで実装する必要がある。

例.年齢が30歳以下(age<=30)のレコードを全て取得したい場合

userオブジェクトストア

nameaddressage
suzukitokyo20
yamadakanagawa19
yoshidachiba31
takahashisaitama60

以下のようなコードとなる

   var tx = db.transaction('user', 'readwrite');
   var store = tx.objectStore('user');
   var req = store.index('name').openCursor();
   var result = [];

    req.onsuccess = function() {
       var cursor = this.result;

       if (cursor) {
           var record = cursor.value;
           if (record.age <= 30) {
                result.push(cursor.value);
            }
            cursor.continue();
        } // 次のレコードが無い場合cursorはundefinedとなる
       else {
            console.log(result); // [{name:suzuki,address:tokyo,age:20}, {name:yamada, address:kanagawa, age:19}]
       }
    };

ブラウザからIndexedDBのデータを削除するには

Windows7

Chrome22

設定 -> 詳細設定を表示 -> プライバシー -> コンテンツの設定 -> 全てのCookieとサイトデータ

から削除できる。
ただし、設定画面から削除できなくなる場合があるので、その場合は以下のフォルダを削除する。

 Users\[ユーザ名]\AppData\Local\Google\Chrome\User Data\Default\IndexedDB\[オリジン].indexeddb.leveldb

Firefox16

以下のフォルダを削除する

 \Users\[ユーザ名]\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxxxx.default\indexedDB\[オリジン]

参考リンク


Copyright (C) 2012-2017 NS Solutions Corporation, All Rights Reserved.