jakearchibald / idb

IndexedDB, but with promises
https://www.npmjs.com/package/idb
ISC License
6.22k stars 348 forks source link

Multiple databases vs one (idb-keyval) #247

Closed pantchox closed 2 years ago

pantchox commented 2 years ago

Hi, I am looking for of an advice. I assumed that after creating a database you can just create a store when ever you want.

I have an app with channels, each channel has files data and links (open graph) data which I save to indexDB in a big mish mash on idb-keyval. Now transitioning to idb library, I planned to create 2 databases, one for files and the other for links data. I assumed that you can create object store on any DB any time - which I was wrong it is only on upgrade event. The idea was that each channel get its own store on each DB, now channels are dynamic they can be deleted and created seamless. I wanted to do it because when deleting a channel I can just delete the store from each of these 2 databases, easy.

But after writing lots of code I understand it is not allowed. In order to avoid files and data of different channels to be in the same DB/store the other option is to create a new DB for each channel that is created and on init/upgrade it will create the files and link data (2 stores) in that channel DB. So when a channel is deleted I just delete the associated DB.

User can have 1-50 channels, what worries me is performance issues or any other thing I did not think about - same as I thought I could create a object store dynamically (which is not the case)

So I am looking for input please :) Thanks!

jakearchibald commented 2 years ago

(closing this, as it isn't an issue with the library, but I'll continue to provide support)

Here's how I'd do this with a single store:

import { openDB, deleteDB } from "https://cdn.jsdelivr.net/npm/idb@7/+esm";

// Just to start from scratch for this demo:
deleteDB("demo").then(async () => {
  const db = await openDB("demo", 1, {
    upgrade(db) {
      const store = db.createObjectStore("channel-data", {
        keyPath: "id",
        autoIncrement: true,
      });

      // Create an index to identify items of a particular channel
      store.createIndex("channel", "channel");
    },
  });

  // Add some items
  {
    const tx = db.transaction("channel-data", "readwrite");
    tx.store.put({
      channel: 1,
      foo: "bar",
    });
    tx.store.put({
      channel: 1,
      hello: "world",
    });
    tx.store.put({
      channel: 2,
      yay: "woo",
    });
    await tx.done;
  }

  // Get all items:
  console.log("all");
  console.log(await db.getAll("channel-data"));

  // Get all from channel 1
  console.log("all from channel 1");
  console.log(await db.getAllFromIndex("channel-data", "channel", 1));

  // Delete all from channel 1
  {
    console.log("deleting all from channel 1");
    const tx = db.transaction("channel-data", "readwrite");
    const keysToDelete = await tx.store.index("channel").getAllKeys(1);
    for (const key of keysToDelete) tx.store.delete(key);
    await tx.done;
  }

  // Get all items:
  console.log("all");
  console.log(await db.getAll("channel-data"));
});
pantchox commented 2 years ago

Thank you VERY MUCH.