API Reference - zuki/Dexie.js GitHub Wiki

クラス

クむック・リファレンスぞゞャンプ

党メ゜ッド

ペヌゞ䞀芧

オペレヌタずフィルタ

アドオン、アダプタ、掟生ワヌク

掟生ワヌク

Typescript

TypescriptでのDexieの䜿甚

ナレッゞベヌス

Q & A

クむック・リファレンス

デヌタベヌスの定矩

var db = new Dexie("MyDatabase");
db.version(1).stores({
    friends: "++id, name, age, *tags",
    gameSessions: "id, score"
});

スキヌマの文法

++ Auto-incremented primary key
& Unique
* Multi-entry index
[A+B] Compound index

文法解説の完党版

アップグレヌド

db.version(1).stores({
    friends: "++id,name,age,*tags",
    gameSessions: "id,score"
});

db.version(2).stores({
    friends: "++id, [firstName+lastName], yearOfBirth, *tags", // Change indexes
    gameSessions: null // Delete table

}).upgrade(function () {
    // Will only be executed if a version below 2 was installed.
    return db.friends.modify(function (friend) {
        friend.firstName = friend.name.split(' ')[0];
        friend.lastName = friend.name.split(' ')[1];
        friend.birthDate = new Date(new Date().getFullYear() - friend.age, 0);
        delete friend.name;
        delete friend.age;
    });
});

デヌタベヌスのバヌゞョンニングに関しおさらに読む

クラスぞのバむンディング

class Friend {
    // プロトタむプメ゜ッド
    save() {
        return db.friends.put(this); // 自身のプロパティのみ保存.
    }

    // プロトタむププロパティ
    get age() {
        return moment(Date.now()).diff (this.birthDate, 'years');
    }
}

db.friends.mapToClass(Friend);

参照: Table.mapToClass()

アむテムの远加

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

参照: WriteableTable.add()

db.people.bulkAdd([{name: "Foo"},{name: "Bar"}]);

参照: WriteableTable.bulkAdd()

アむテムの曎新

db.friends.put({id: 4, name: "Foo", age: 33});

参照: WriteableTable.put()

db.friends.bulkPut([
    {id: 4, name: "Foo2", age: 34},
    {id: 5, name: "Bar2", age: 44}
]);

参照: WriteableTable.bulkPut()

db.friends.update(4, {name: "Bar"});

参照: WriteableTable.update()

db.customers
    .where("age")
    .inAnyRange([ [0, 18], [65, Infinity] ])
    .modify({discount: 0.5});

参照: WriteableCollection.modify()

アむテムの削陀

db.friends.delete(4);

参照: WriteableTable.delete()

db.friends.bulkDelete([1,2,4]);

参照: WriteableTable.bulkDelete()

db.logEntries
    .where('timestamp').below(Date.now() - 100000)
    .delete();

参照: WriteableCollection.delete()

アむテムのク゚リ

db.friends
    .where("age").between(20, 25)
    .offset(150)
    .limit(25)
    .toArray()
    .then(function (friends) {
        //
    });
db.friends
    .where("name").equalsIgnoreCase("josephine")
    .each(function(friend) {
        console.log("Found Josephine: " + JSON.stringify(friend));
    })
    .then(...);
db.friends
    .where("name")
    .startsWithAnyOfIgnoreCase(["a", "b", "c"])
    .toArray()
    .then (function (friends) {
        ...
    });

参照: Table.where(), WhereClause, Collection

db.friends
    .where('age')
    .inAnyRange([[0,18], [65, Infinity]])
    .modify({discount: 0.5});

参照: Table.where(), WhereClause, WriteableCollection.modify()

db.friends
    .filter(friend => /a/i.test(friend.name))
    .toArray()
    .then(function (friendsContainingLetterA) {
        ...
    });

参照: Table.filter()

db.friends
    .where('[firstName+lastName]')
    .equals(["Hillary", "Clinton"])
    .first()
    .then(function (president) {
        ...
    });

[耇合むンデックスに関しおさらに読む](Compound Index)

db.friends
    .where('age').above(25)
    .or('shoeSize').below(8)
    .or('interests').anyOf('sports', 'pets', 'cars')
    .modify(friend => friend.tags.push("marketing-target"));

参照: Collection.or()

TOP-Xアむテムの抜出

db.gameSessions
    .orderBy("score")
    .reverse()
    .limit(5)
    .toArray()
    .then(function(sessions) {
        console.log (
            "My 5 top sessions: " +
            sessions.map(function (s) { return s.date }));
    });

参照: Table.orderBy(), Collection.reverse(), Collection.limit()

結合

var db = new Dexie('music');
db.version(1).stores({
    genres: '++id,name',
    albums: '++id,name,year,*tracks',
    bands: '++id,name,*albumIds,genreId'
});

var all = Dexie.Promise.all;

function getBandsStartingWithA () {

    // ク゚リ
    return db.bands
        .where ('name')
        .startsWith ('A')
        .toArray()

    .then (bands => {

        // Set genre and albums as direct properties on each result
        return all (bands.map (band =>
          all([
            db.genres.get (band.genreId),
            db.albums.where('id')
              .anyOf (band.albumIds)
              .toArray ()
          ]).then (result => {
            [band.genre, band.albums] = result;
            return band;
          });
        ));
    });
}

PromiseのYield凊理

spawn()

Dexie.spawn(function*() {

    var id = yield db.friends.add({name: 'Simon', age: 3});
    console.log("Simon got id: " + id);

    var oldFriends = yield db.friends.where('age').above(75).toArray();
    console.log("Old friends: " + oldFriends.map(f => f.name));

    // 9歳以䞊のすべおの友達に犬をあげる:
    var addedPetIds = yield db.transaction('rw', db.friends, function* () {
        // 犬をもらえるすべおの友達の䞻キヌを埗る:
        var primaryKeys = yield db.friends.where('age').above(8).primaryKeys();
        return yield Dexie.Promise.all(
            // 新たに犬を远加しお、その倖郚キヌに䞊げる友達をセット
            primaryKeys.map(friendId => db.pets.add({kind: 'dog', ownerId: friendId})
        );
    });

}).catch (function (err) {
    console.error (err.stack);
});

async()

var birthday = Dexie.async(function* (friendId) {
    yield db.friends
        .where('id')
        .equals(friendId)
        .modify(friend => {
            friend.age++;
        });
});

birthDay(2).catch(err => console.error(err.stack));

トランザクションの実行

function goodFriends() {
    return db.friends
        .where('tags')
        .equals('close-friend');
}

function addComment(friendId, comment) {
    return db.friends
        .where('id')
        .equals(friendId)
        .modify(friend => {
            friend.comments.push(comment);
        });
}

function spreadYourLove() {
    // 倉曎のアトミック化:
    return db.transaction('rw', db.friends, function* () {
        var goodFriendKeys = yield goodFriends().primaryKeys();
        yield Dexie.Promise.all(
            goodFriendKeys.map(id => addComment(id, "I like you!"))
        );
    });
}

䞊のコヌドスニペットは「トランザクションなし」のコヌド(関数 goodFriends() ず addComment()) を再利甚しお、トランザクション内(spreadYourLove())で実行できるこずを瀺しおいる。

参照: Dexie.transaction()

芪トランザクション

// すでにトランザクションを䜿甚しおいる他の関数を呌ぶ1぀の倧きなアトミックな倉曎にする
db.transaction('rw', db.friends, db.diary, function*() {
    yield spreadYourLove();
    yield db.diary.log({date: Date.now(), text: "Today I successfully spread my love"});
}).catch (err => {
    console.error ("I failed to spread my love :( " + err.stack);
});

䞊のコヌドスニペットは実際にトランザクションを認識しおいるコヌドも再利甚でき、そのような耇数の関数をたずめお1぀のアンブレラトランザクションにカプセル化するこずもできるこずを瀺しおいる

参照: Dexie.transaction()

非同期APIを䜿う

Dexie.js は非同期APIである。同期APIでぱラヌは通垞䟋倖を䜿っお凊理される。これは非垞に䟿利である。なぜなら、いたるずころで゚ラヌをチェックするこずなく、より高いレベルで䟋倖をキャッチすれば良いからである。非同期APIでは通垞、成功および゚ラヌむベントを䜿っお、操䜜が終了した際に通知する。indexedDBは䟋倖ず゚ラヌむベントの組み合わせを䜿っお呌び出し元(caller)に通知するので、゚ラヌ凊理を正しくコヌディングするこずは非垞に面倒である。各々すべおのリク゚ストに察しおtry..catchずrequest.onerrorの䞡者を行う必芁があるからである。Dexie.jsはECMAScript6準拠のPromises を䜿うこずでこの問題を解決し、゚ラヌ凊理をtry..catch゚ラヌ凊理を行う同期APIず同じくらい簡単なものにしおいる。

Promisesを䜿う

(Dexie.jsのような)PromiseベヌスのAPIはむベントベヌスのAPIずいうより同期APIのように芋えるだろう。ただし、結果を返すのではなくPromiseを返す。ECMAScript6のPromiseは2぀のメ゜ッド、then() ず catch()を持っおいる。これらのメッ゜ドは各々操䜜が成功たたは倱敗した際に呌ばれるコヌルバックを芁求する。Dexieの非同期メ゜ッドはすべおPromiseのむンスタンスを返す。これにより、プロゞェクトに含たれる䟋で芋られるように、APIは䜿いやすいものになっおいる。

Promiseの互換性

DexieのPromisesは A+ / ES6 準拠であり、bluebird や Q、ネむティブPromiseなどの他のPromiseラむブラリずも魔法のようにうたく動かすこずができる。DexieのPromisesはTypescript やES7のasync / await でも䜿甚するこずができる。ただし、Dexie.Promiseはトランザクション内の操䜜を行う際の䜿甚に留めおおくこずが重芁である。そうでないずindexedDB自䜓の制限により実行䞭のトランザクションが意図より早くコミットされるこずがある。ただし、トランザクションの最終結果db.transaction()により返される最終的なPromiseは他の任意のPromiseラむブラリず安党に混ぜるこずも、倉換するこずも可胜である。

Promise固有デヌタ

DexieのPromisesはスレッド・ロヌカル・ストレヌゞ ず同じパタヌンをサポヌトしおおり、実行䞭のPromiseおよびその子Promiseにバむンドされるスタティックプロパティを持぀こずができる。これはAngularのzone.js ず同じであるが、察象はPromiseだけであり、globalを倉曎するこずはできない。Dexie.jsずそのトランザクションAPIはそれに匷く䟝存しおいる。なぜなら、それによりコヌドはトランザクションオブゞェクトを枡すこずなく実行䞭のトランザクションを知るこずができるからである。 Promise-Specific Data doc supports a pattern similar to where it is possible to have static properties that is bound to the executing promise and all it's child-promises. This is similar Angular's zone.js but only for Promises and without having to modify globals. Dexie.js and it's transaction API heavily depends on it since it enables code to be aware of the currently executing transaction without having to pass transaction objects around. Promise固有デヌタ.

䟋倖凊理

DexieではindexedDBずは異なり、Promise.catch()メ゜ッドずいう、䟋倖を捉える単䞀の方法が存圚する。暙準的なtry..catch()を䜿甚する必芁はどこにもない。その理由はcallerに耇数の゚ラヌ凊理の方法を考える必芁をなくすこずである。トランザクションを䜿甚するず、デヌタベヌス操䜜毎にpromiseのcatch()凊理をするのではなく、トランザクションの最終地点の䞀箇所ですべおの゚ラヌを捉えられるずいう利点もある。任意の未捕捉゚ラヌ゚ラヌむベントであれ、䟋倖であれ、コヌド䞭の倉数のミススペルであれは実行䞭のトランザクションをアボヌトさせ、返り倀のPromise のrejectを呌び出し、トランザクションスコヌプに付䞎された任意のcatch()節を呌び芚たすこずになる。

db.transaction('rw', db.friends, function() {

    ...

    window.MissSpelledVar.NonExistingVar = 3; // 倱敗する!

}).catch (function (err) {

    // トランザクションはアボヌト!
    console.error(err);

});

すべおのトランザクションPromiseはcatchされるか、callerに返されるべきである。このパタヌンに埓わない堎合は、Promise.on('error') が発火する。

Dexie.Promise.on('error', function (err) {
    // 未捕捉のDB関連の゚ラヌず䟋倖をすべお補足する
    console.error(err);
});

補足は凊理を意味する!

トランザクション内でデヌタベヌス操䜜からのPromiseを補足した堎合、それは凊理されたず考えられ、トランザクションはアボヌトしない。これは、トランザクションがアボヌトするこずを期埅しお、ログ出力のためだけにトランザクション内でPromiseを補足する時、䞀般的な萜ずし穎になる可胜性がある。これを避ける方法は凊理しない゚ラヌをre-throwするこずである。

db.transaction('rw', db.friends, function() {

    db.friends.add({id: 1, name: "Foo"}).catch(function(e) {
        console.error("Failed to add Foo friend");
        throw e; // トランザクションをアボヌトするためにRethrow
    });

})

トランザクションを䜿う

2぀以䞊の操䜜を行いたい堎合は垞にトランザクションを䜿うこずでコヌドを簡玠化できる。トランザクションを䜿うこずにより以䞋の利点を享受できる。

  • デヌタベヌスを曎新䞭に䜕らかの゚ラヌあらゆる皮類の゚ラヌむベントや䟋倖が発生した堎合、トランザクションはアボヌトし、すべおの倉曎はロヌルバックされる。
  • したくなければPromiseを凊理する必芁がたったくない。それを凊理できるようにすべおはトランザクションにカプセル化される。
  • 操䜜はすべお同期的に曞くこずができ、凊理を行う前に前の凊理が終わるのを埅぀必芁がない以䞋の2぀めのコヌド䟋を参照。
  • write操䜜埌のread操䜜もwriteの終了を埅たずに行うこずができる。この堎合でも、結果にはすべおの倉曎が含たれる。これが可胜なのは、珟圚のトランザクションで実行する保留䞭のwrite操䜜がある堎合はすべおの操䜜がキュヌむングされるからである。
  • どの゚ラヌも芋逃されるこずはない。最終的なcatch()メ゜ッドですべおの゚ラヌあらゆる皮類の゚ラヌむベントず通垞の䟋倖の䞡者を補足する。

以䞋はトランザクションブロックの利甚法である:

db.transaction('rw', db.friends, db.pets, function () {
    // 発生した任意のデヌタベヌス゚ラヌむベントはトランザクションをアボヌトさせ
    // 以䞋のcatch()メ゜ッドに送られる。
    // 任意の䟋倖が投げられおも同じ。

    return db.pets.add({name: 'Bamse', kind: 'cat'}).then(function (petId) {
        return db.friends.add({name: 'Kate', age: 89, pets: [petId]});
    });

}).catch(function (error) {
    // ゚ラヌをログ出力したり衚瀺したり

    console.error (error.stack || error);

});

泚:

  • 'friends' ず 'pets' はVersion.stores()メ゜ッドを䜿っお登録されたobjectStoreである。
  • read操䜜しかしない堎合は、"rw" は "r" に眮き換える。
  • トランザクション内の連続的なデヌタベヌス操䜜で発生する゚ラヌも、䞀連のthen()コヌルバックで発生する䟋倖も、トランザクションのcatch()メ゜ッドで補足される。
  • 倱敗したDB操䜜を明瀺的に補足した堎合は、トランザクションがアボヌトされない堎合がある。
db.transaction('rw', db.friends, function() {
    db.friends.add({id:1, name:"Fredrik"});
    db.friends.add({id:1, name:"Fredrik"}).catch(function (err) {
        // 同じ䞻キヌを2床登録しようずするずもちろん倱敗する。しかし、
        // この゚ラヌを明瀺的に補足しおいるのでトランザクションはアボヌトしない。
        // こうするこずでトランザクションを継続させるこずができる。
        // トランザクションをアボヌトさせたい堎合は、
        // Dexie.currentTransaction.abort()を実行するか、䟋倖を投げるか、
        // 単に次を実行する:
        // return Dexie.Promise.reject(err);
    });
}).then (function () {
    alert ("Transaction successfully completed");
});

トランザクションを䜿甚しおいる堎合は、add(), put(), update(), delete(), modify()操䜜の察象を次の行で凊理を埅぀こずなく問い合わせるこずができる。埅぀こずはフレヌムワヌクで凊理されおいる。トランザクションを䜿うこずで毎回 .then()をコヌルする必芁がなく、いかにコヌドが簡玠化するか、以䞋のコヌドの違いを芋おもらいたい。

トランザクションを䜿甚しないコヌド䟋
db.friends.add({ name: "Ulla Bella", age: 87, isCloseFriend: 0 }).then(function () {

    return db.friends.add({ name: "Elna", age: 99, isCloseFriend: 1 });

}).then(function (){

    return db.friends.where("age").above(65).each(function (friend) {
        console.log("Retired friend: " + friend.name);
    });

}).catch(function (error) {

    console.error(error);

})
トランザクションを䜿甚したコヌド䟋
db.transaction("rw", db.friends, function () {

    db.friends.add({ name: "Ulla Bella", age: 87, isCloseFriend: 0 });
    db.friends.add({ name: "Elna", age: 99, isCloseFriend: 1 });
    db.friends.where("age").above(65).each(function (friend) {
        console.log("Retired friend: " + friend.name);
    });

}).catch(function (error) {

    console.error(error);

});

䞊の䟋では、同䞀のトランザクション内ではadd()操䜜を埅぀必芁が無いこずを瀺しおいる。

IndexedDBのトランザクションが持぀自動コミット

IndexedDBはtick内で䜿甚されなくなるや吊やトランザクションをコミットする。これはトランザクションスコヌプ内では他の非同期APIを呌んではいけない少なくずもそれの終了を埅っおいいけないこずを意味する。それをするずトランザクションの䜿甚を継続しよずするや吊やTransactionInactiveErrorが投げられるこずになる。これはIndexedDBのふるたいなのでDexie.Promiseでコヌルをカプセル化しおも回避するこずはできない。

入れ子のIndexedDBトランザクション

バヌゞョン0.9.8以降, Dexieは入れ子のトランザクションサポヌトした。

db.transaction('rw', db.friends, db.pets, function () {
    // メむントランザクションブロック
    db.transaction('rw', db.pets, function () {
       // サブトランザクションブロック
    });
});

入れ子のトランザクションが持぀胜力は、トランザクションを䜿甚する関数が、そのすべおのコヌルをより倧きなトランザクションに包み蟌むより高レベルなコヌドにより再利甚できるこずである。

より詳现なトランザクションの䜿甚法に぀いおはDexie.transaction()も参照されたい。

⚠ **GitHub.com Fallback** ⚠