IN Operator equivalence in indexedDB

我的梦境 提交于 2021-02-05 05:37:27

问题


I want to execute this query select * from properties where propertyCode IN ("field1", "field2", "field3")

How can I achieve this in IndexedDB I tried this thing

getData : function (indexName, params, objectStoreName) {
            var defer = $q.defer(),
                db, transaction, index, cursorRequest, request, objectStore, resultSet, dataList = [];
            request = indexedDB.open('test');
            request.onsuccess = function (event) {
                db = request.result;
                transaction = db.transaction(objectStoreName);
                objectStore = transaction.objectStore(objectStoreName);
                index = objectStore.index(indexName);
                cursorRequest = index.openCursor(IDBKeyRange.only(params));
                cursorRequest.onsuccess = function () {

                    resultSet = cursorRequest.result;
                    if(resultSet){
                        dataList.push(resultSet.value);
                        resultSet.continue();
                    }
                    else{
                        console.log(dataList);
                        defer.resolve(dataList);
                    }
                };

                cursorRequest.onerror = function (event) {
                    console.log('Error while opening cursor');
                }
            }
            request.onerror = function (event) {
                console.log('Not able to get access to DB in executeQuery');
            }
            return defer.promise;

But didn't worked. I tried google but couldn't find exact answer.


回答1:


If you consider that IN is essentially equivalent to field1 == propertyCode OR field2 == propertyCode, then you could say that IN is just another way of using OR.

IndexedDB cannot do OR (unions) from a single request.

Generally, your only recourse is to do separate requests, then merge them in memory. Generally, this will not have great performance. If you are dealing with a lot of objects, you might want to consider giving up altogether on this approach and thinking of how to avoid such an approach.

Another approach is to iterate over all objects in memory, and then filter those that don't meet your conditions. Again, terrible performance.

Here is a gimmicky hack that might give you decent performance, but it requires some extra work and a tiny bit of storage overhead:

  • Store an extra field in your objects. For example, plan to use a property named hasPropertyCodeX.
  • Whenever any of the 3 properties are true (has the right code), set the field (as in, just make it a property of the object, its value is irrelevant).
  • When none of the 3 properties are true, delete the property from the object.
  • Whenever the object is modified, update the derived property (set or unset it as appropriate).
  • Create an index on this derived property in indexedDB.
  • Open a cursor over the index. Only objects with a property present will appear in the cursor results.

Example for 3rd approach

var request = indexedDB.open(...);
request.onupgradeneeded = upgrade;

function upgrade(event) {
  var db = event.target.result;
  var store = db.createObjectStore('store', ...);

  // Create another index for the special property
  var index = store.createIndex('hasPropCodeX', 'hasPropCodeX');
}

function putThing(db, thing) {

  // Before storing the thing, secretly update the hasPropCodeX value
  // which is derived from the thing's other properties
  if(thing.field1 === 'propCode' || thing.field2 === 'propCode' || 
    thing.field3 === 'propCode') {
    thing.hasPropCodeX = 1;
  } else {
    delete thing.hasPropCodeX;
  }

  var tx = db.transaction('store', 'readwrite');
  var store = tx.objectStore('store');
  store.put(thing);
}

function getThingsWherePropCodeXInAnyof3Fields(db, callback) {
  var things = [];
  var tx = db.transaction('store');
  var store = tx.objectStore('store');
  var index = store.index('hasPropCodeX');
  var request = index.openCursor();
  request.onsuccess = function(event) {
    var cursor = event.target.result;
    if(cursor) {
      var thing = cursor.value;
      things.push(thing);
      cursor.continue();
    } else {
      callback(things);
    }
  };
  request.onerror = function(event) {
    console.error(event.target.error);
    callback(things);
  };
}

// Now that you have an api, here is some example calling code
// Not bothering to promisify it
function getData() {
  var request = indexedDB.open(...);
  request.onsuccess = function(event) {
    var db = event.target.result;
    getThingsWherePropCodeXInAnyof3Fields(db, function(things) {
      console.log('Got %s things', things.length);
      for(let thing of things) {
        console.log('Thing', thing);
      }
    });
  };
}


来源:https://stackoverflow.com/questions/39249744/in-operator-equivalence-in-indexeddb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!