kinto.js
kinto.js copied to clipboard
IDB: use a multiEntry index and 'structured' keys
As suggested by Andrew in https://bugzilla.mozilla.org/show_bug.cgi?id=1486980#c36
Example pseudocode:
objectStore.createIndex("app_indices", "appIndices", { multiEntry: true });
function fancyPut(idbDataStore, collectionName, collectionIndicesMap, appObj) {
const appIndices = collectionIndicies.map([indexName, indexEvalPath]) => {
// for the example, assume the key is not nested...
const appVal = appObj[indexEvalPath];
if (Array.isArray(appVal)) {
throw new Error("The value can't be an array for our current bounds cleverness.");
}
// Create an index key that's array-structured so we can bound its
// key-space.
return [collectionName, indexName, appVal];
});
const wrappedObj = {
actualObj: appObj
appIndices
};
return idbDataStore.put(wrappedObj);
}
async function findWithIndex(idbDataStore, collectionName, indexName, appExact,
[appLow, appHigh]) {
// [collectionName, indexName] lower-bounds all [collectionName, indexName, ...]
// because a shorter array is by definition less than a longer array that is
// equal up to their shared length.
// [collectionName, indexName, []] upper-bounds all [collectionName, indexName, ...]
// because arrays are always greater than strings/dates/numbers. So as long
// as the other contents of the index are non-arrays, we're good.
const wholeIndexBounds = IDBKeyRange.bound(
[collectionName, indexName],
[collectionName, indexName, []],
true, true); // exclusive range for the edge-case values.
const exactIndexBounds = IDBKeyRange.only([collectionName, indexName, appValue]);
const rangeBounds = IDBKeyRange.bound(
[collectionName, indexName, appLow],
[collectionName, indexName, appHigh],
false, false); // assume caller meant inclusive.
// DO ACTUAL INDEX STUFF
return wrappedObj.actualObj;
}