Html5 IndexedDB - 通过键检索值

发布于 2024-12-17 19:35:13 字数 68 浏览 4 评论 0原文

在大多数教程中,都展示了如何通过使用游标迭代来从对象存储中检索所有记录。 但是如何通过键“myKey”从对象存储中检索值?

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" ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伴我老 2024-12-24 19:35:13

如果您正在寻找简单的键/值存储,那么您可能需要考虑 localStorage。它比使用 IndexedDB 简单得多。它仅适用于字符串(到目前为止),但对象可以通过 JSON 对象轻松字符串化。

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' ) ) );

也就是说,只有当您需要获取一个键或一系列键的多个值时,才需要游标从 IndexedDB 中的键获取单个值。要从键获取值,您需要执行以下两种操作之一:

1) 如果 myKey 是您的主键(在创建商店时添加):

var request = transaction.get( key );

然后您可以添加 onsuccessonerror 回调来解析生成的事件对象,您需要从中提取 event.target.result 值。

2) 如果 myKey 位于非主索引(您在创建商店后添加的索引)中,则打开事务上的索引,然后打开索引上的游标。

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

至于游标(您可能会更频繁地讨论它,因为每当您在同一键下存储多个值时,您就需要一个游标),您也可以使用它们来检索单个键的值。 规范说:

键范围可以由单个值组成。

您需要使用 IDBKeyRange 对象生成 keyRange。这是来自 MIT 许可的 InDB (我正在进行的 IndexedDB 包装器)的辅助方法,该方法处理在单个值(例如InDB.range.get( value ))或键范围上打开光标。

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;
        }
    }

获得 keyRange 后,您可以执行以下两件事之一:

1) 如果 myKey 是您的主键(在创建商店时添加),则您可以在您的交易(带有可选方向)。

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

2) 如果 myKey 位于非主索引(您在创建商店后添加的索引)中,则打开事务上的索引,然后打开索引上的游标。

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

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 );
随心而道 2024-12-24 19:35:13

有一些库可以帮助您使用 IndexedDB,例如 DexieJsStoreLocalForageSFDatabase-js

对我来说,使用 SFDatabase-js 更容易,因为用法几乎与 < a href="https://github.com/ScarletsFiction/Scarlets/wiki/Database" rel="nofollow noreferrer">PHP 版本(使用 MySQL/Redis 作为数据库时)。它也适用于 NodeJS。
您所需要的只是定义数据库索引结构并初始化数据库。

var myDB = new SFDatabase('myDB', {
    websql:false,
    idbVersion:1,
    databaseStructure:{
        Users:{
            // rowid -> always unique and incremental
            name:['text', 'unique']
        }
    }
}, function(){
    // database initialized
});

之后,您可以在数据库中存储几乎任何内容。

myDB.insert('Users', {name:"Alex", age:17});
myDB.insert('Users', {name:"Ander", age:12});
myDB.insert('Users', {name:"Bell", age:30, admin:true});

如果您想获取单行数据,可以使用get

myDB.get('Users', 'age', {name:"Ander"}, console.log);
//-> 12

myDB.get('Users', ['name', 'age'], {admin:true}, console.log);
//-> {name:"Bell", age:30}

并且还获取多行数据。

// Age more than 15
myDB.select('Users', ['name'], {'age[>]':15}, console.log);
//-> [{name: "Alex"}, {name: "Bell"}]

// Any name with 'e' and without 'A', and limit to two result
myDB.select('Users', ['name'], {'name[~]':'e', 'name[!~]'=>'A', LIMIT:2}, console.log);
//-> [{name: "Bell"}]

There are some library that can help you using IndexedDB like Dexie, JsStore, LocalForage, and SFDatabase-js.

For me, it's easier with SFDatabase-js because the usage is almost similar with the PHP version when using MySQL/Redis as database. It also working for NodeJS.
All you need is define the database indexes structure and initialize the database.

var myDB = new SFDatabase('myDB', {
    websql:false,
    idbVersion:1,
    databaseStructure:{
        Users:{
            // rowid -> always unique and incremental
            name:['text', 'unique']
        }
    }
}, function(){
    // database initialized
});

And after that, you can store almost anything in the database.

myDB.insert('Users', {name:"Alex", age:17});
myDB.insert('Users', {name:"Ander", age:12});
myDB.insert('Users', {name:"Bell", age:30, admin:true});

If you like to obtaining single row data you can use get.

myDB.get('Users', 'age', {name:"Ander"}, console.log);
//-> 12

myDB.get('Users', ['name', 'age'], {admin:true}, console.log);
//-> {name:"Bell", age:30}

And also obtaining multi row data.

// Age more than 15
myDB.select('Users', ['name'], {'age[>]':15}, console.log);
//-> [{name: "Alex"}, {name: "Bell"}]

// Any name with 'e' and without 'A', and limit to two result
myDB.select('Users', ['name'], {'name[~]':'e', 'name[!~]'=>'A', LIMIT:2}, console.log);
//-> [{name: "Bell"}]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文