Understanding the basics
Creating Database vs opening existing
IndexedDB (and Dexie) has a built-in system for db installation and schema upgrades. Many people think they will have to check if the database needs to be created, and then run different code depending on whether or not the database was installed on the client. This is not needed. Your Dexie code can be declarative (you declare what tables and schemas you have in current and previously released versions and you let Dexie / indexedDB handle the situation where a database wasn't created yet, needs upgrading, or is already on latest version).
IndexedDB is designed for handling database creation and upgrades through the onupgradeneeded
event, and defines the schema there. There is no native method for checking whether or not a database exists. Dexie adds a declarative schema syntax on top of that so that you don't need to subscribe to the onupgradeneeded
event either.
Declarative Schema
The database schema is declarative, not imperative.
Primary and secondary indexes
When declaring friends: 'name, age'
the first property implicitly becomes the primary index (also called primary key). This declaration states that we want a table called 'friends' where the property 'name' is the primary key, and where we add a secondary index on 'age'. A primary key is a unique key, meaning you can never store two objects with the same primary key in the same table. For this reason, most examples you'll see will use a property 'id' or 'key' as primary key instead. You will also see examples using a ++
before the primary index, which makes it auto-incremented. You may also see examples with a &
before a secondary index, making that index unique the same way as primary indexes are implicitly unique.
Understanding the flow
First time
The first time a browser hits the appdb.js code, the following happens:
The database is created
The populate event is triggered to allow the developer to populate the database
The db.open() promise resolves
Second time
The database is simply opened and the promise resolves.
Modify Schema
When you need to modify the schema, also update the version number. In the sample below, we remove the "name" index and add two new indexes "firstName", "lastName" to the friends table. We also change the version number from 1 to 2 in order for this change to have effect:
In older version of Dexie (version <3.0), you were required to keep all previous version declarations alongside the new one:
Migrate Data
When migrating existing data, you need to keep the old version alongside the new one and attach an upgrade function to the new version.
Changing a few tables only
If you are just adding or changing a few tables, you do not need to repeat the schemas of all the old tables if those tables are already present in an older version being kept.
Deleting tables
Since it is not mandatory to repeat old table definitions, Dexie has to be explicitly informed about table deletion. This is done by specifying null as the table schema.
Changes in Dexie 3.0
Before version 3.0, it was not recommended to modify an existing schema, but to instead always add a new version with the new declaration. Since Dexie version 3.0, you only have to do that when an upgrader is attached to the new version. In other cases, you only need to edit the schema and modify the version number.
Conclusions
You never need to check whether the database needs to be created. Your code is just declarative.
Whenever editing the schema, also remember to update the version number.
Historical versions that have upgraders attached should be kept as long as there are people out there that may have it installed.
To delete a table, add a new version specifying the table as null.