Ben Dilts
Ben Dilts

Reputation: 10745

IndexedDB keyPath to somewhere deep in an object?

When you create an objectStore or index in IndexedDB, you specify a "keyPath" that says where in your object to look for the value that should be the key on the store or index. I have objects that look like this:

{doc:{id:4}}

Is there a way for me to specify a keyPath that will get that ID? I tried dotting it (keyPath = "doc.id"), but it didn't work. Do I have to copy all my possible keys into the top layer of my objects?

Upvotes: 1

Views: 5840

Answers (2)

Chris Nielsen
Chris Nielsen

Reputation: 14738

According to the specification, your dot notation is correct. The browser is supposed to follow the steps for extracting a key from a value using a key path, which should result in the functionality you desire.

Chrome 12 works as described. I have not been able to get Firefox 4.0 or 5.0 to behave this way, and suspect this is a bug in their implementation (or else the specification was different when they implemented it).

Firefox 4.0 - 5.0 DOES correctly parse a key path if it contains no periods. As you say, this means you must have keys at the top level of your object if you want it to work in Firefox.

Here is some working example code (for Chrome 12 and Firefox 4.0 - 5.0) that illustrates the difference:

(function () {

    var db, idb = window.mozIndexedDB || window.webkitIndexedDB;

    idb.open("test").onsuccess = function (ev) {
        db = ev.target.result;
        db.setVersion("1.0").onsuccess = setUpDatabase;
    };

    function setUpDatabase(ev) {
        var x, store;

        for (x = 0; x < db.objectStoreNames.length; x += 1) {
            db.deleteObjectStore(db.objectStoreNames[x]);
        }

        var store = db.createObjectStore("test", {
            keyPath: (window.mozIndexedDB) ? 'moz' : 'doc.webKit'
        });

        store.add({ moz: 1, doc: { webKit: 3, name: 'webkit!'  }});
        store.add({ moz: 3, doc: { webKit: 1, name: 'mozilla!' }});

        // Wait for the setVersion transaction to end...
        // This is an example. Typically control would return to the
        // event loop after this point.
        window.setTimeout(getSomeValue, 1000);
    };

    function getSomeValue() {
        db.transaction("test").objectStore("test").get(3).onsuccess = showValue;
    }

    function showValue(ev) {
        var value = ev.target.result.doc;
        alert('name: ' + value.name);
        // Don't forget to close your connections!
        db.close();
    }

}());

Upvotes: 4

Jonas Sicking
Jonas Sicking

Reputation: 1192

In the initial implementation of IndexedDB in Firefox this didn't work correctly as you've discovered.

However by now it's been fixed for quite a while, so you should be able to use it without problem.

Upvotes: 0

Related Questions