With given values of this shape:
interface Entity {
id: number
created_at: Date
updated_at: Date
title: string
}
And this storage and its indexes:
const store = database.createObjectStore("entities", {
keyPath: "id",
autoIncrement: true,
});
store.createIndex("index_by_creation_date", ["created_at", "id"], {
unique: true,
});
store.createIndex("index_by_update_date", ["updated_at", "id"], {
unique: true,
});
I assumed I could get different sorting order by just opening cursors on different indexes:
interface Props {
transaction: IDBTransaction,
index_name: "index_by_creation_date" | "index_by_update_date",
offset?: number,
limit?: number
}
function getEntityIDs(
{
transaction,
index_name,
offset = 0,
limit = 20
}: Props,
onSuccess: (results: Entity["id"][]) => void
) {
const objectStore = transaction.objectStore("entities");
const index = objectStore.index(index_name);
const results: Entity["id"][] = [];
let isAdvancing = offset !== 0;
const cursorRequest = index.openKeyCursor();
cursorRequest.onsuccess = (event) => {
const cursor = (event.target as typeof cursorRequest).result;
if (cursor && results.length < limit) {
if (isAdvancing === true) {
cursor.advance(offset);
isAdvancing = false;
return;
}
const id = cursor.primaryKey as Entity["id"];
results.push(id);
cursor.continue();
} else {
onSuccess(results);
}
}
}
But both indexes iterate in the same order. They have to be compound because the timestamps are generated at transaction creation time for related operations and creation/update are implemented as batch operations, so entities created/updated in the same transaction will have exact the same timestamp.
Turns out it was a red herring and I set up and used indexes properly. The issue was me getting actual data in a separate request using the list of IDs from this function, but not sorting them in the same order as said list. And since it was creating creating the cursor on the object store, the order of values was the same as default sorting on object store.