IN Operator equivalence in indexedDB

时间:2016-08-31 12:31:14

标签: javascript range indexeddb

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 个答案:

答案 0 :(得分:1)

如果您认为IN基本上等同于field1 == propertyCode OR field2 == propertyCode,那么您可以说IN只是使用OR的另一种方式。

IndexedDB无法通过单个请求执行OR(联合)。

通常,您唯一的办法是单独执行请求,然后将它们合并到内存中。通常,这不会有很好的表现。如果你正在处理很多对象,你可能要考虑完全放弃这种方法,并考虑如何避免这种方法。

另一种方法是迭代内存中的所有对象,然后过滤那些不符合条件的对象。再次,糟糕的表现。

这是一个花哨的黑客,可能会给你不错的性能,但它需要一些额外的工作和一点点的存储开销:

  • 在对象中存储额外字段。例如,计划使用名为hasPropertyCodeX
  • 的属性
  • 每当3个属性中的任何一个为真(具有正确的代码)时,设置字段(如,只是使其成为对象的属性,其值无关紧要)。
  • 当3个属性都不为真时,从对象中删除属性。
  • 每当修改对象时,更新派生属性(根据需要设置或取消设置)。
  • 在indexedDB中为此派生属性创建索引。
  • 在索引上打开一个光标。只有具有属性的对象才会出现在光标结果中。

第3种方法的例子

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