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
Solution with 2 successive queries using a compound index:
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();
}
};
}