Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Html5 IndexedDB - retrieve a value by its key

Tags:

html

indexeddb

In most turorials it is shown how to retrieve all the records from an object store by iterating over them with a cursor. But how do you retrieve a value from an object store by its key "myKey" ?

like image 662
Matthew Avatar asked Nov 24 '11 11:11

Matthew


1 Answers

If you're looking for simple key/value storage then you might want to consider localStorage. It's much more straightforward than using IndexedDB. It only works with strings (so far) but objects are easily stringified via the JSON object.

console.log( 'BEFORE', localStorage.getItem( 'test-key' ) );
localStorage.setItem( 'test-key', JSON.stringify( { 'foo': Math.round( Math.random() * 1000 ) } ) );
console.log( 'AFTER', JSON.parse( localStorage.getItem( 'test-key' ) ) );

That said, you don't need a cursor to get a single value from a key in IndexedDB, only if you need to get multiple values for a key or range of keys. To get a value from a key, you do one of two things:

1) If myKey is your primary key (added when creating the store):

var request = transaction.get( key );

You can then add an onsuccess and onerror callback to parse the resulting event object, from which you'll want to extract the event.target.result value.

2) If myKey is in a non-primary index (one you've added after creating the store), you open the index on your transaction and then open the cursor on the index.

var transaction_index = transaction.index( index );
var request = transaction_index.get( key );

As for cursors (which you likely see discussed more often because you'll need one whenever you have multiple values stored under the same key), you can use those to retrieve values for a single key as well. Says the spec:

A key range may consist of a single value.

You'll need to generate a keyRange using the IDBKeyRange object. Here's the helper method for that from MIT-licensed InDB (my work-in-progress IndexedDB wrapper), which handles opening a cursor on a single value (e.g. InDB.range.get( value )) or a key range.

InDB.range.get = function ( value, left_bound, right_bound, includes_left_bound, includes_right_bound ) {
        if ( InDB.exists( left_bound ) && InDB.exists( right_bound ) && InDB.exists( includes_left_bound ) && InDB.exists( includes_right_bound ) ) {   
            return IDBKeyRange.bound( left_bound, right_bound, includes_left_bound, includes_right_bound ); 
        } else if ( InDB.exists( left_bound ) && InDB.exists( includes_left_bound ) ) {
            return IDBKeyRange.lowerBound( left_bound, includes_left_bound );
        } else if ( InDB.exists( right_bound ) && InDB.exists( includes_right_bound ) ) {
            return IDBKeyRange.upperBound( right_bound, includes_right_bound );
        } else if ( InDB.exists( value ) ) {
            return IDBKeyRange.only( value );
        }  else {
            return false;
        }
    }

Once you have the keyRange, you do one of two things:

1) If myKey is your primary key (added when creating the store), you open up a regular cursor on your transaction (with an optional direction).

var request = transaction.openCursor( keyRange, direction );

2) If myKey is in a non-primary index (one you've added after creating the store), you open the index on your transaction and then open the cursor on the index.

var transaction_index = transaction.index( index );
var request = transaction_index.openCursor( keyRange, direction );
like image 154
buley Avatar answered Oct 06 '22 01:10

buley