【问题标题】:OR or IN operation in IndexedDBIndexedDB 中的 OR 或 IN 操作
【发布时间】:2014-03-15 04:52:35
【问题描述】:

有没有办法对 IndexedDB 中的同一属性执行 OR 或 IN 查询?

换句话说,我如何得到结果,

SELECT * FROM MyTable WHERE columnA IN ('ABC','DFT') AND columnB = '123thd'

谢谢!

【问题讨论】:

    标签: indexeddb


    【解决方案1】:

    如果没有多次请求,就无法进行开箱即用的ORIN 之类的查询。通常,此类问题的模式是“超出范围,提取比您需要的更多条目,并将其过滤为完全匹配”。

    Chrome 团队 has proposed 一个 openKeyCursor() 方法作为此类查询的解决方案(感谢 Kyaw Tun 的建议,他是 SO 参与者和 ydn 的作者),但它不是标准也没有在其他浏览器中采用。

    我能想到的最好的解决方案类似于w3线程的Comment #4

    • 使用值 '123thd' 在 columnB 上打开精确的键光标
    • 所有这些记录中的光标,匹配对象 columnA 值 'ABC' 和 'DFT'

    如果您通常期望columnB 为“123thd”的结果数量很大,并且大多数没有值“ABC”或“DFT”,那么您可能应该改为打开两个游标 -一个在columnA 上,带有值“ABC”,另一个在值“DFT”上。这是一种更复杂的方法,因为您必须手动合并两个结果集。

    【讨论】:

      【解决方案2】:

      使用复合索引的 2 个连续查询的解决方案:

      1. 在列 A 和列 B 上创建复合索引。有关示例,请参阅 this post
      2. 使用范围参数 ['ABC','123thd'] 进行查询并迭代其结果。
      3. 使用范围参数 ['DFT','123thd'] 进行查询并迭代其结果。

      使用派生属性进行 1 个查询的解决方案:

      这种方法的缺点是您需要知道您计划执行的查询和 必须为每个查询调整此方法。这是你甚至应该做的事情 用 SQL。不幸的是,由于许多开发人员不关心正确的查询计划,这并不是那么明显,所以在使用 indexedDB 之前,它就像一个额外的要求学习和开始使用。但是,正确的查询计划确实会产生更好的性能。

      // In onupgradeneeded
      function myOnUpgradeNeeded(event) {
        var db = event.target.result;
        var store = db.createObjectStore('MyTable');
      
        // Create a compound index on the derived property of columnA
        // and the normal property of columnB
        store.createIndex('A_ABC_OR_DFT_AND_B', ['ABC_OR_DFT_FLAG','columnB']);
      }
      
      
      function wrappedPut(db, obj, callback) {
        // Set the flag property
        // indexedDB cannot index booleans, so we use simple integer representation
        // where 1 represents true, 0 represents false. But we can go further since
        // we know that undefined properties dont appear in the index.
      
       if(obj.columnA=='ABC'||obj.columnA=='DFT') {
         obj.ABC_OR_DFT_FLAG = 1;
       } else {
         delete obj.ABC_OR_DFT_FLAG;
       }
      
       put(db, obj, callback);
      }
      
      // In your add/update function
      function put(db, obj, callback) {
       db.transaction('MyTable','readwrite').objectStore('myTable').put(obj).onsuccess = callback;
      }
      
      // Voila, a single efficient high speed query over all items 
      // in MyTable where columnA is ABC or DFT and where columnB 
      // is 123thd, using a single index, without using a 3rd party
      // library, and without doing some horrible double cursor stuff
      // in javascript, and just using the indexedDB API.
      function runTheABCDFT123Query(db, onSuccess, onComplete) {
        var tx = db.transaction('MyTable');
        tx.onComplete = onComplete;
        tx.objectStore('MyTable').index('A_ABC_OR_DFT_AND_B').openCursor(
          IDBKeyRange.only([1,'123thd'])).onsuccess = function(event) {
          if(event.target) {
            onSuccess(event.target.value);
            event.target.continue();
          }
        };
      }
      

      【讨论】:

      • 谢谢,乔希,所以我想我必须执行 2 个查询,对吧?有没有办法在单个查询中做 OR?
      【解决方案3】:

      indexedDB API 中不存在此功能。您只能过滤单个索引。您可以尝试围绕 indexedDB API 编写的库之一。其中一些提供额外的过滤器功能。

      【讨论】:

        【解决方案4】:

        这是一个简单的查询,等同于使用 JsStore Library 的 sql 查询

        var Connection = new JsStore.Instance("MyDatabase");
        Connection.select({
            From: "MyTable",
            Where:{
                columnA : {In:['ABC','DFT')]},
                columnB : '123thd'
            },
            OnSuccess:function (results){
                console.log(results);
            },
            OnError:function (error) {
                console.log(error);
            }
        });
        

        希望这会节省您的时间和代码:)。

        【讨论】:

          猜你喜欢
          • 2014-11-01
          • 2019-01-11
          • 2018-12-05
          • 2013-09-08
          • 1970-01-01
          • 2021-04-11
          • 2010-11-10
          • 1970-01-01
          相关资源
          最近更新 更多