treo icon indicating copy to clipboard operation
treo copied to clipboard

dynamic schemas

Open wclr opened this issue 9 years ago • 4 comments

Treo (idb-schema) currently assumes quite static schemas (with certain stores). I think it would be useful to have ability to dynamicly add stores in databases (with auto increased verions). I think sometimes it is more easy to manage objects in separate stores rather than pushing everyting into one store.

I maybe wrong. But is there a good pattern of dynamicly adding stores in dbs and working with them with treo?

wclr avatar Feb 18 '16 12:02 wclr

The reason treo uses static schemas, because this is how IndexedDB works.

A couple years ago, I've been implementing dynamic schemas. The core idea is to do more checks during Promise resolve (check if store exists, if not close db, increment version and open new db with new store, listen on versionchange to reload db object to support multiple tabs).

Could you explain your use case? Maybe you can reuse one store and just use prefixed keys (store1-*, store2-*). We could think about some treo-* or idb-* plugin to cover this usage.

alekseykulikov avatar Feb 18 '16 14:02 alekseykulikov

Let say you need to store different dictionaries for diffrent languages (50-150k records each). Probably there would bee need to remove whole dictionary, or add new one. It is possible to implement using one store I'm not sure why don't like this idea to put everything in one store.

Another use case would be storing many child items that refer to some parent objects. With separate stores all the keys can be inserted/removed/selected without need of messing with single store ranges and rebuilding indexes.

But in some part management becomes more complicated when you need to add another store with the same "structure" indexes should be added as well. Or when you need to add/remove index to "structure", you should implement it for all stores that actually have to have the same structure, with is a little against indexed db concept.

wclr avatar Feb 18 '16 15:02 wclr

Thank you for details. It seems, one store approach could work :)

await db.dictionaries.batch(records) // add 50k records with key starting wiht fr-*
await db.dictionaries.getAll({ gte: 'fr-', lt: 'fr-\uffff' }) // get all French records
await db.dictionaries.clear({ gte: 'fr-', lt: 'fr-\uffff' }) // remove French records

What's missing:

  • store.getAll({ gte: 'fr-', lt: 'fr\uffff' }) is a bit ugly, getAll({ match: 'fr-*' }) could be better good attion to idb-range
  • store.clear(range) does not support range. I wanted to propose it to IndexedDB 2.0 spec as addition to .getAll, but for now work around with .openCursor(range) + cursor.delete() should work.

Based on this functionality, we can implement approach similar to https://github.com/dominictarr/level-sublevel

const fr = db.dictionaries.subStore('fr-')
await fr.batch(records) // automatically prefix keys
await fr.getAll() // get all 
await fr.clear() // remove all French records

alekseykulikov avatar Feb 18 '16 15:02 alekseykulikov

Ok thanks, will see how it will work out.

wclr avatar Feb 19 '16 11:02 wclr