В Dexie.js структура базы данных определяется версионной схемой, где каждая версия описывает набор object stores и индексов. Любое изменение структуры — добавление, удаление или изменение таблиц — выполняется исключительно через механизм версионирования, поскольку IndexedDB не допускает прямой модификации схемы без открытия транзакции на обновление версии базы.
Каждая версия базы в Dexie.js фиксирует состояние схемы через метод:
db.version(n).stores({...})
Где:
n — номер версии базы данных;stores — строковое описание object stores и их
индексов.Dexie.js интерпретирует схему как декларацию состояния базы на конкретной версии. При открытии базы происходит сравнение текущей версии, сохранённой в IndexedDB, с новой версией приложения. Если номер версии увеличен, запускается процесс миграции.
Добавление новой таблицы реализуется через расширение схемы в новой версии базы. При этом все ранее существующие хранилища должны быть повторно объявлены, поскольку схема в Dexie.js не наследуется автоматически между версиями.
Пример добавления нового object store:
db.version(1).stores({
users: "++id,name,email"
});
db.version(2).stores({
users: "++id,name,email",
orders: "++id,userId,createdAt"
});
orders создаётся только в версии 2;users сохраняет свою структуру без
изменений;При необходимости инициализации данных используется блок миграции:
db.version(2).stores({
users: "++id,name,email",
orders: "++id,userId,createdAt"
}).upgrade(tx => {
return tx.table("orders").add({
userId: 1,
createdAt: Date.now()
});
});
Удаление таблицы в Dexie.js не выполняется явно через отдельный метод. Исключение object store из схемы новой версии приводит к его автоматическому удалению при апгрейде базы.
Пример удаления хранилища:
db.version(1).stores({
users: "++id,name,email",
logs: "++id,message,createdAt"
});
db.version(2).stores({
users: "++id,name,email"
});
В данном случае:
logs существует в версии 1;logs при обновлении версии.Удаление store сопровождается рядом особенностей:
Часто миграции комбинируют добавление новых таблиц и удаление старых:
db.version(1).stores({
users: "++id,name,email",
sessions: "++id,userId,token"
});
db.version(2).stores({
users: "++id,name,email",
authTokens: "++id,userId,token,expiresAt"
});
В этом случае происходит:
authTokens;sessions;users без изменений.При замене одного store другим часто требуется перенос данных.
Dexie.js предоставляет транзакционный контекст через
upgrade, позволяющий читать старые данные и записывать
новые.
Пример миграции:
db.version(2).stores({
users: "++id,name,email",
authTokens: "++id,userId,token,expiresAt"
}).upgrade(async tx => {
const oldSessions = await tx.table("sessions").toArray();
const transformed = oldSessions.map(s => ({
userId: s.userId,
token: s.token,
expiresAt: Date.now() + 3600 * 1000
}));
await tx.table("authTokens").bulkAdd(transformed);
});
Особенности транзакции:
Прямого механизма переименования object store в IndexedDB не существует. В Dexie.js переименование реализуется как комбинация удаления и добавления:
db.version(1).stores({
sessions: "++id,userId,token"
});
db.version(2).stores({
authSessions: "++id,userId,token"
}).upgrade(async tx => {
const oldData = await tx.table("sessions").toArray();
await tx.table("authSessions").bulkAdd(oldData);
});
После миграции старый store автоматически удаляется, поскольку он отсутствует в новой схеме.
Каждая новая версия должна включать полное описание всех актуальных
хранилищ. Частичная декларация схемы недопустима, поскольку Dexie.js
рассматривает stores() как полный снимок структуры на
момент версии.
Нарушение этого правила приводит к:
Изменение индексов или первичных ключей также требует новой версии. Например:
db.version(1).stores({
users: "++id,name,email"
});
db.version(2).stores({
users: "++id,email,username"
});
При этом:
upgrade.При сложных изменениях применяется последовательное увеличение версий:
db.version(1).stores({
users: "++id,name,email"
});
db.version(2).stores({
users: "++id,name,email",
logs: "++id,message"
});
db.version(3).stores({
users: "++id,name,email",
logs: "++id,message",
settings: "++id,key,value"
});
Каждая версия представляет атомарный шаг миграции. Dexie выполняет их по порядку, гарантируя целостность данных между переходами.
Upgrade-транзакция обладает особыми характеристиками:
Это обеспечивает согласованное состояние схемы после завершения обновления.
Часто встречающиеся проблемы при изменении структуры:
Корректная стратегия изменения хранилищ строится на нескольких принципах:
upgrade;