IndexedDB: one-to-many relation - How?

I am trying to find the best approach to work with one to many relations and indexedDB.

By one to many I mean relations between object stores. E.g.

Object store: artists:
Object store: albums
(and maybe another level
Object store: songs)

Can anyone point to guideline for how this is best done?

Is one of the indexedDB wrappers the answer to do this in a simple way?


Well, for starters, indexedDB itself has no relations. So whatever you do, you get to do the hooking up yourself. You could have object stores that you then join on IDs, that’s what I do. Have an array of IDs and map that to values in the other store.


Thanks Martin. Do you have an implemented example of your approach?

Any opinions on IndexedDB wrappers?

I have my own wrapper. It looks a bit like this:

The matching is just the matching array operation. In the simplest case it’s a map, but usually I implement it the other way. Get too many of the potential matches for the IDs in the array and then filter them down. But you could also do that while going through an index (possibly limited with a so you don’t have to go through everything etc.)

Some Promise based wrapper is definitely handy. I wrote my own as well :slight_smile: but it’s very simple one:

async function dbTransaction(tableName: DB_TABLE, transactionMode: IDBTransactionMode) {
  const db = await _dbPromise;
  return db.transaction([tableName], transactionMode).objectStore(tableName);

async function dbOperation<T>(transaction: IDBObjectStore | IDBIndex, fnName: KeysOfType<IDBObjectStore & IDBIndex, Function>, ...params: any[]): Promise<T> {
  return new Promise((resolve, reject) => {
    // @ts-ignore - I'm not sure this can be done "by the book" without loosing the flexibility
    const idbRequest = transaction[fnName].apply(transaction, params);
    idbRequest.onerror = reject;
    idbRequest.onsuccess = () => {

async function dbTransactionOperation<T>(tableName: DB_TABLE, transactionMode: IDBTransactionMode, fnName: KeysOfType<IDBObjectStore & IDBIndex, Function>, ...params: any[]) {
  return dbOperation<T>(await dbTransaction(tableName, transactionMode), fnName, ...params)

It’s in TypeScript, but you can just remove types and it will work fine. Using these functions you can then easily query all your data with Promises.

Also as a user of IndexedDB, make sure to vote for some bugs! :smiley: (this one is 6 years old!)

Do anyone have opinions / experience with

It seems to be the goto wrapper.