【问题标题】:Html5 IndexedDB - retrieve a value by its keyHtml5 IndexedDB - 通过其键检索值
【发布时间】:2012-01-05 13:37:05
【问题描述】:

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

【问题讨论】:

    标签: html indexeddb


    【解决方案1】:

    如果您正在寻找简单的键/值存储,那么您可能需要考虑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 );
    

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

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

    您需要使用IDBKeyRange 对象生成keyRange。这是来自MIT-licensed 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 );
    

    【讨论】:

    • 似乎“var request = transaction.get(key);”生成错误:“未捕获的 TypeError:对象 # 没有方法 'get'”。我想我需要在 objectStore 上调用 .get() 方法,而不是你写的事务。是这样吗?
    • 您只能通过事务访问对象存储数据,但您在objectStore 上调用get() 是正确的。 transaction 的 var 声明未在此处显示,但类似于 event.objectStore( database )
    • 值得注意的是,您打开了数据库上的事务 (w3.org/TR/IndexedDB/#idl-def-IDBDatabase) 和 var event = database.transaction( [ database ], type, timeout );
    • “它比使用 IndexedDB 更简单”,除非您使用 Web Worker 或 Service Worker:您不能使用它。
    【解决方案2】:

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

    对我来说,使用SFDatabase-js 更容易,因为在使用 MySQL/Redis 作为数据库时,其用法与 PHP version 几乎相似。它也适用于 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"}]
    

    【讨论】:

      猜你喜欢
      • 2018-12-22
      • 2014-01-26
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多