Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting specific ids from Indexeddb

In my project I'm using browser's indexed-DB and I would like to retrieve some objects from the db with specific ids. According to MDN you could use ranges to get the results you want:

According to MDN:

// Only match "Donna"
var singleKeyRange = IDBKeyRange.only("Donna");

// Match anything past "Bill", including "Bill"
var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill");

// Match anything past "Bill", but don't include "Bill"
var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true);

// Match anything up to, but not including, "Donna"
var upperBoundOpenKeyRange = IDBKeyRange.upperBound("Donna", true);

// Match anything between "Bill" and "Donna", but not including "Donna"
var boundKeyRange = IDBKeyRange.bound("Bill", "Donna", false, true);

// To use one of the key ranges, pass it in as the first argument of openCursor()/openKeyCursor()
index.openCursor(boundKeyRange).onsuccess = function(event) {
  var cursor = event.target.result;
  if (cursor) {
    // Do something with the matches.
    cursor.continue();
  }
};

However what do you do if you wish to get an array of specific ids that are not in order and are not sequential (ex:[91,819,34,24,501]) with a single request?

like image 968
0x_Anakin Avatar asked Feb 17 '15 14:02

0x_Anakin


People also ask

Where is IndexedDB stored?

More specifically, IndexedDB data is stored in the browser profile folder.

What is IndexedDB and how is it used by PWA?

It lets you store just about anything in the user's browser. In addition to the usual search, get, and put actions, IndexedDB also supports transactions. Here is the definition of IndexedDB on MDN: "IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs.

What is IndexedDB in angular?

IndexedDB is a low-level API for the client-side storage of significant amounts of structured data, including files/blobs. This API uses indexes to enable high-performance searches of this data.


3 Answers

You can't do this with a single request, but you can fire off multiple requests in parallel:

var keys = [91,819,34,24,501];
var results = [];
keys.forEach(function(key) {
  store.get(key).onsuccess = function(e) {
    results.push(e.target.result);
    if (results.length === keys.length) {
       // you're done!
    }
  };
});

Note that requests are required to execute in order, so the order of the results array will match the order of the keys array. If a key is not found, the corresponding result index will contain undefined.

(There's a feature request for Indexed DB to support this directly: https://github.com/w3c/IndexedDB/issues/19 but no final API design yet.)

like image 88
Joshua Bell Avatar answered Oct 17 '22 11:10

Joshua Bell


Based on your comment, it sounds like you want to do something like SELECT objects FROM objects WHERE object.id = 1 OR object.id = 2 OR object.id = 5, as a single query (request). Unfortunately, indexedDB cannot do OR style queries (unions). It can only do AND style queries (intersections).

There is a possible solution if the various ids you want to retrieve are known a-priori. You can simply store an additional group-id property, put the related ids into distinct groups, and then query by group-id. This obviously does not work if the ids you want to retrieve overlap (appear in more than one group), or are variable (object to group membership changes from query to query).

like image 30
Josh Avatar answered Oct 17 '22 11:10

Josh


Getting multiple objects by keys in 1 go is possible by using a cursor.

The keys need to be sorted.

var keys = [91,819,34,24,501].sort(function(a, b) {
   return a - b;
});
var results = [];
var i = 0;
var cursorReq = store.openCursor();
cursorReq.onsuccess = function(e) {
   var c = e.target.result;
   if(!c) { return; /* done */ }
   while(c.key > keys[i]) {
      i++;
      if(i === keys.length) { return; /* done */ }
   }
   if(c.key === keys[i]) { // found
      results.push(cursor.value);
      c.continue();
   } else { c.continue(keys[i]); }
}
like image 44
dehart Avatar answered Oct 17 '22 13:10

dehart