OR or IN operation in IndexedDB

前端 未结 4 893
一整个雨季
一整个雨季 2020-12-19 14:19

Is there a way to do an OR or IN query on the same property in IndexedDB?

Another word, how do I get the results for,

SELECT * FROM MyTable WHERE col         


        
4条回答
  •  孤城傲影
    2020-12-19 15:04

    Solution with 2 successive queries using a compound index:

    1. Create a compound index on columnA and columnB. See this post for an example.
    2. Query with range parameter ['ABC','123thd'] and iterate over its results.
    3. Query with range parameter ['DFT','123thd'] and iterate over its results.

    Solution with 1 query using a derived property:

    The drawback of this approach is you need to know the queries you plan to execute and have to adapt this method for each query. This is something you should be doing even with SQL. Unfortunately, because many developers do not bother with proper query planning, this is not so obvious, so it is like an additional requirement to learn and start using before using indexedDB. However, proper query planning does yield better performance.

    // 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();
        }
      };
    }
    

提交回复
热议问题