0

I have this code (Indexeddb/Dexie)

db1.RestrictionsImport.where('idx').equals(n).toArray().then(function(x){...})

This works fine but I have an multitude of collections with "Restrictions" for which I have to perform the search(es). If I do this:

var collection= ['RestrictionsImport','RestrictionsPrice','RestrictionsCountry','RestrictionsPart',...etc]
db1.collection[0].where('idx').equals(n).toArray().then(function(x){...})

It crashes:

index.html:251 Uncaught TypeError: Cannot read property 'where' of undefined at index.html:251   (anonymous) @ index.html:251

This series of restriction types can count from a few to dozens depending on other queries so I have to put the Dexie queries in a loop, I cannot simply write them one after another...

Some suggestions ?

Thanks in advance, H.D.

Huqe Dato
  • 235
  • 1
  • 16

2 Answers2

1

Depending on your variations of data I would probably recommend using a single table 'restrictions' and put the type of restriction as a property (let's call it 'type').

If you want efficient indexes, use compound index of [type+idx] instead of just idx.

Your queries could then be something like :

db.restrictions.where('[type+idx]`).equals (['country', n])

You would need to think of the compound index as a two items array. For example if you have an age property you would like to index and search for items where type == 'person' and age > 25, do :

db restrictions.where('[type+age]`).between (
    ['person', 25],
    ['person', Infinity]) 

Case insensitive searches are not possible though.

IndexedDB was not designed for dynamically adding tables on the fly. It is possible though, but you will need to manage the version number of your database somehow and keep in mind that each time you need to add a new table, other tabs working towards the same database will either block your schema update request, or have to close down and stop functioning as expected.

David Fahlander
  • 5,058
  • 1
  • 20
  • 19
  • Thanks @David Fahlander, this is a better design indeed, but I have to re-write a lot of code in this way. I was wondering whether is possible to do it only by looping through the collections, somehow. – Huqe Dato Jul 13 '17 at 09:47
1

Yes. db.tables is the property to access in order to get an array of the defined tables:

db.tables.forEach(table => {
    console.log(table.name);
});

A table is an instance of Dexie.Table

If you for example need to put a new item into each table, do:

Promise.all(db.tables.map(table => table.put(newItem)))
  .then(...)
  .catch(...)

The above code also possible to use within a transaction:

db.transaction('rw', db.tables, () => {
  return Dexie.Promise.all(db.tables.map(table => {
    return table.put(newItem);
  }));
}).then({
  ...
}).catch({
  ...
});
David Fahlander
  • 5,058
  • 1
  • 20
  • 19