17

I want to sort results obtained from indexedDB.
Each record has structure {id, text, date} where 'id' is the keyPath.

I want to sort the results by date.

My current code is as below:

  var trans = db.transaction(['msgs'], IDBTransaction.READ);
  var store = trans.objectStore('msgs');

  // Get everything in the store;
  var keyRange = IDBKeyRange.lowerBound("");
  var cursorRequest = store.openCursor(keyRange);

  cursorRequest.onsuccess = function(e) {
    var result = e.target.result;
    if(!!result == false){
        return;
    }
    console.log(result.value);
    result.continue();
  };
Josh
  • 17,834
  • 7
  • 50
  • 68
vivek.m
  • 3,213
  • 5
  • 33
  • 48
  • See http://stackoverflow.com/questions/12084177/in-indexeddb-is-there-a-way-to-make-a-sorted-compound-query/15625231#15625231 In short, use an array of keys as an index. – 173210 Mar 27 '16 at 02:15

3 Answers3

27

Actually you have to index the date field in the msgs objectStore and open an index cursor on the objectStore.

var cursorRequest = store.index('date').openCursor(null, 'next'); // or prev 

This will get the sorted result. That is how indexes are supposed to be used.

Steve Gattuso
  • 7,644
  • 10
  • 44
  • 59
Kyaw Tun
  • 12,447
  • 10
  • 56
  • 83
10

Here's the more efficient way suggested by Josh.

Supposing you created an index on "date":

// Use the literal "readonly" instead of IDBTransaction.READ, which is deprecated:
var trans = db.transaction(['msgs'], "readonly");
var store = trans.objectStore('msgs');
var index = store.index('date');

// Get everything in the store:
var cursorRequest = index.openCursor();
// It's the same as:
// var cursorRequest = index.openCursor(null, "next");
// Or, if you want a "descendent ordering":
// var cursorRequest = index.openCursor(null, "prev");
// Note that there's no need to define a key range if you want all the objects

var res = new Array();

cursorRequest.onsuccess = function(e) {

    var cursor = e.target.result;
    if (cursor) {
        res.push(cursor.value);
        cursor.continue();
    }
    else {
        //print res etc....
    }
};

More on cursor direction here: http://www.w3.org/TR/IndexedDB/#cursor-concept

IDBIndex API is here: http://www.w3.org/TR/IndexedDB/#idl-def-IDBIndex

Andrei Cojocaru
  • 151
  • 1
  • 6
  • How do I get sorted results when index's keypath is an array. say the array is of type `[string, Date]`. I want the result to be sorted by `Date` field. – Sri Jul 27 '21 at 11:29
-2

Thanks to zomg, hughfdjackson of javascript irc, I sorted the final array. Modified code as below:

var trans = db.transaction(['msgs'], IDBTransaction.READ);
var store = trans.objectStore('msgs');

// Get everything in the store;
var keyRange = IDBKeyRange.lowerBound("");
var cursorRequest = store.openCursor(keyRange);

var res = new Array();

cursorRequest.onsuccess = function(e) {
    var result = e.target.result;
    if(!!result == false){
        **res.sort(function(a,b){return Number(a.date) - Number(b.date);});**
        //print res etc....
        return;
    }
    res.push(result.value);
    result.continue();
};
vivek.m
  • 3,213
  • 5
  • 33
  • 48
  • 12
    This kind of misses the entire point of using indexedDB. You would want to use an indexedDB 'index' to sort by a non-primary-key property. You can then open a cursor on an index and iterate in one of four ways (next,prev,nextUnique,prevUnique). Your choice of sorting non-natively is not optimal. – Josh Apr 15 '13 at 18:41
  • That makes sense. Thanks! I will keep that in mind when I use indexedDB next time. – vivek.m Jun 20 '13 at 03:52