indexedDB objectStore.get() always returns undefined despite results in DB
Asked Answered
M

2

8

I've been reworking an older project and making some improvements and I can no longer seem to figure out how to load a single entry from the indexedDB. I have cleared the DB and done a fresh import and I can see all the records (including the one I am using for the entryID) in the chrome inspectors Resource section. I have tried pulling all sorts of ID numbers, all of which I can confirm are in the DB from the inspector, they all return undefined. This is the code I'm using.

/*
    This loads up a specific entry and fills in the #entry-details div with it's data. This div is placed overtop the search 
    content so that when it is closed the user remains exactly where they were and the search does not need to re-process.
*/
function getEntryDetails(){

    var entryID = 193; // just for now, this will be grabbed from somewhere else later

    // Where going to need a varible to store all this generated HTML in
    var html = '';

    // First we need to load up the indexedDB and get the record in question.
    var db = indexedDB.open('pediaCache');

    // lets get a couple of the errors out of the way.
    db.onerror=function(e){html += 'There was an error loading the database.<br/>'+e;}
    db.onblocked=function(e){html += 'Database access blocked.<br/>'+e;}

    // Now for when things go the right way
    db.onsuccess=function(e){
        var db = e.target.result;

        // Get the requested entry
        console.log('Attempting to load entry ID '+entryID);
        var transaction = db.transaction(['entries'],'readonly');
        var objectStore = transaction.objectStore('entries');
        var entry = objectStore.get(entryID);

        entry.onerror = function(e) {
            console.log('error');
            console.log(e.target.result);
            console.log(e);
        };
        entry.onsuccess = function(e) {
            console.log('success');
            console.log(e.target.result);
            console.log(e);
        };

    }

}

This is really just some slightly modified code from the original version (since this functionality is the same, I really only modified the database and ObjectStore names both here and in the importer). Running this code in Chrome (triggered manually after I know all other DB related functions are done) does fire the "onsuccess" even, just with an undefined result (as if the entry was not in the DB, but again I have checked it's in there).

As requested, the contents of console.dir(e):

{
    "path": {
        "length": 0
    },
    "cancelBubble": false,
    "returnValue": true,
    "srcElement": {
        "readyState": "done",
        "transaction": {
            "onerror": null,
            "oncomplete": null,
            "onabort": null,
            "error": null,
            "db": {
                "onversionchange": null,
                "onerror": null,
                "onclose": null,
                "onabort": null,
                "objectStoreNames": {
                    "0": "entries",
                    "length": 1
                },
                "version": 3,
                "name": "pediaCache"
            },
            "mode": "readonly"
        },
        "source": {
            "autoIncrement": false,
            "transaction": {
                "onerror": null,
                "oncomplete": null,
                "onabort": null,
                "error": null,
                "db": {
                    "onversionchange": null,
                    "onerror": null,
                    "onclose": null,
                    "onabort": null,
                    "objectStoreNames": {
                        "0": "entries",
                        "length": 1
                    },
                    "version": 3,
                    "name": "pediaCache"
                },
                "mode": "readonly"
            },
            "indexNames": {
                "0": "title",
                "length": 1
            },
            "keyPath": null,
            "name": "entries"
        },
        "error": null
    },
    "defaultPrevented": false,
    "timeStamp": 1420434102528,
    "cancelable": false,
    "bubbles": false,
    "eventPhase": 0,
    "currentTarget": null,
    "target": {
        "readyState": "done",
        "transaction": {
            "onerror": null,
            "oncomplete": null,
            "onabort": null,
            "error": null,
            "db": {
                "onversionchange": null,
                "onerror": null,
                "onclose": null,
                "onabort": null,
                "objectStoreNames": {
                    "0": "entries",
                    "length": 1
                },
                "version": 3,
                "name": "pediaCache"
            },
            "mode": "readonly"
        },
        "source": {
            "autoIncrement": false,
            "transaction": {
                "onerror": null,
                "oncomplete": null,
                "onabort": null,
                "error": null,
                "db": {
                    "onversionchange": null,
                    "onerror": null,
                    "onclose": null,
                    "onabort": null,
                    "objectStoreNames": {
                        "0": "entries",
                        "length": 1
                    },
                    "version": 3,
                    "name": "pediaCache"
                },
                "mode": "readonly"
            },
            "indexNames": {
                "0": "title",
                "length": 1
            },
            "keyPath": null,
            "name": "entries"
        },
        "error": null
    },
    "type": "success"
}

And the objectStore creation (onupgradeneeded).

    // We need to be able to update the db schema (or create it for that matter)
    db.onupgradeneeded=function(e){
        var db = e.target.result;

        // In the future some of theme might want to get commented out...
        postMessage({'status':'importing','message':'Upgrading local database.'});
        // Check if the table is in there, if it's not then create it
        console.log(db.objectStoreNames);
        if(db.objectStoreNames.contains('entries')==false){
            var db = db.createObjectStore('entries');

            // Create the indexes so we can more easily search and sort and stuff (just one, we sort by name, everything else done by magic)
            db.createIndex('title'  ,'ZTITLE'   ,{unique:false});

        }

    };
Mitchmitchael answered 5/1, 2015 at 3:15 Comment(4)
What are the arguments you pass to createObjectStore? Copy and paste the relevant statement from within your onupgradeneeded function. Just a guess, but are you not using a keyPath?Bushtit
No I'm not, however I wasn't in the old code either. The only code that this is based on can be found on github here: github.com/pgooch/GamepediaViewer/ just as in that example I am supplying a key when I .put() the records in with the following line action.put(entries[n],entries[n].ZUID); Just as a test I went ahead and changed the upgrade and put functions to use a keyPath instead and the results are still the same.Mitchmitchael
Have you tried interacting directly with indexedDB without the use of IndexedDBShim.js? I would at least rule out the shim as the source of the problem. It could easily be a problem with the shim not setting event.target.result (which console.dir clearly shows is undefined, which makes no sense at all).Bushtit
The new version does not use the shim (meaning it has to be accessed in chrome, but thats where I develop anyway).Mitchmitchael
M
29

Found the problem, hopefully nobody make the same simple mistake I did but in case someone does and runs across this question here's what the problem was.

The key I was adding into the database was a string. The key I was requesting was an int.

Don't be like me, check your data types.

Mitchmitchael answered 7/1, 2015 at 1:53 Comment(2)
Mine as well! Hovering over the key in the "storage inspector" also pointed out these 2 nasty "sInapprehensive
Phew .. it was turning out to be a murder mystery ..Marmoreal
B
1

Use the appropriate keyPath when you create an index/store. The following expressions are not the same!

store.createIndex(this.indexes.prevNodeKey, "prevNodeKey");
store.createIndex(this.indexes.prevNodeKey, ["prevNodeKey"]);
db.createObjectStore(this.storeNames.configs, {keyPath: "price"});
db.createObjectStore(this.storeNames.configs, {keyPath: ["price"]});

I created an index with an array keyPath and then could not query anything from the index even though the types were equal.

Probably, if you define a keyPath as an array, then you should query using array:

someIndex.getKey(["value"]))
Burgle answered 19/5, 2022 at 22:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.