DexieJS 和 IndexedDB 中的完全动态索引规范
Fully dynamic index specification in DexieJS and IndexedDB
对于我的应用程序,我希望用户能够为 table.
指定索引列
我知道要执行此操作,我需要关闭数据库,指定一个新版本,然后再次打开它。为了尽量减少这样做的影响,我将应用程序的这个自定义部分放在它自己的数据库中。
这是我如何执行此操作的示例。
import Dexie from 'dexie';
const db = new Dexie("CustomPeople");
db.version(1).stores({
people: '++id'
});
function testColumnAdd() {
modifyColumns(['firstName'])
.then(() => {
db.people.add({
firstName: 'John'
});
})
.then(() => {
return modifyColumns(['firstName', 'lastName']);
})
.then(() => {
db.people.add({
firstName: 'John',
lastName: 'Smith'
});
});
}
function modifyColumns(columns) {
return db.open()
.then(() => {
const originalVersion = db.verno;
console.log('original version: ' + originalVersion);
db.close();
return originalVersion;
})
.then((originalVersion) => {
const newVersion = originalVersion + 1;
console.log('adding columns ' + columns.join(','));
console.log('new version version ' + newVersion);
db.version(newVersion).stores({
leads: '++id,' + columns.join(',')
});
return db.open();
});
}
每次调用 testColumnAdd() 时,这似乎都能正常工作。
但是,在页面重新加载后,testColumnAdd() 的第一个触发器给出了以下异常。
Unhandled rejection: VersionError: The requested version (10) is less than the existing version (70).
考虑到所有 Dexie 最初能看到的是版本 1,这绝对是有道理的。有没有一种方法可以让我读取当前版本并使用它?
一般来说,是否有更好的方法来处理用户定义的索引?
Dexie 有动态模式。它通过省略 db.version(x) 的规范来启用。它基本上将数据库打开到当前版本。
new Dexie("CustomPeople").open().then (db => {
console.log("Version", db.verno);
console.log("Tables", db.tables.map(({name, schema}) => ({
name,
schema
}));
});
但是当您需要修改模式(或最初创建它)时,您必须像您已经做的那样做 - 在打开它之前指定 db.version(db.verno + 1)。
需要重新打开数据库以更改架构的原因是 IndexedDB 本身的限制/功能。
编辑:我刚刚更新了文档:http://dexie.org/docs/Dexie/Dexie.open()#dynamic-schema-manipulation
我不确定这是否是 Dexie 最初的意图,但我发现了另一种围绕现有数据库初始化的方法。
出于其他原因,我需要将列的定义存储在单独的数据库中。当我加载现有数据库时,我只是根据该元数据构建正确的版本。
const dbName = 'CustomPeople';
const exists = await Dexie.exists(dbName);
if (exists) {
var db = new Dexie(dbName);
const dynamicDB = await db.open();
const existingVersionNumber = dynamicDB.verno;
const columns = await ExternalDBService.getColumns();
db.close();
db = new Dexie(dbName);
db.version(existingVersionNumber).stores({
People: columns
});
return db.open();
} else {
db = new Dexie(dbName);
db.version(1).stores({
People: []
});
db.open();
}
对于我的应用程序,我希望用户能够为 table.
指定索引列我知道要执行此操作,我需要关闭数据库,指定一个新版本,然后再次打开它。为了尽量减少这样做的影响,我将应用程序的这个自定义部分放在它自己的数据库中。
这是我如何执行此操作的示例。
import Dexie from 'dexie';
const db = new Dexie("CustomPeople");
db.version(1).stores({
people: '++id'
});
function testColumnAdd() {
modifyColumns(['firstName'])
.then(() => {
db.people.add({
firstName: 'John'
});
})
.then(() => {
return modifyColumns(['firstName', 'lastName']);
})
.then(() => {
db.people.add({
firstName: 'John',
lastName: 'Smith'
});
});
}
function modifyColumns(columns) {
return db.open()
.then(() => {
const originalVersion = db.verno;
console.log('original version: ' + originalVersion);
db.close();
return originalVersion;
})
.then((originalVersion) => {
const newVersion = originalVersion + 1;
console.log('adding columns ' + columns.join(','));
console.log('new version version ' + newVersion);
db.version(newVersion).stores({
leads: '++id,' + columns.join(',')
});
return db.open();
});
}
每次调用 testColumnAdd() 时,这似乎都能正常工作。
但是,在页面重新加载后,testColumnAdd() 的第一个触发器给出了以下异常。
Unhandled rejection: VersionError: The requested version (10) is less than the existing version (70).
考虑到所有 Dexie 最初能看到的是版本 1,这绝对是有道理的。有没有一种方法可以让我读取当前版本并使用它?
一般来说,是否有更好的方法来处理用户定义的索引?
Dexie 有动态模式。它通过省略 db.version(x) 的规范来启用。它基本上将数据库打开到当前版本。
new Dexie("CustomPeople").open().then (db => {
console.log("Version", db.verno);
console.log("Tables", db.tables.map(({name, schema}) => ({
name,
schema
}));
});
但是当您需要修改模式(或最初创建它)时,您必须像您已经做的那样做 - 在打开它之前指定 db.version(db.verno + 1)。
需要重新打开数据库以更改架构的原因是 IndexedDB 本身的限制/功能。
编辑:我刚刚更新了文档:http://dexie.org/docs/Dexie/Dexie.open()#dynamic-schema-manipulation
我不确定这是否是 Dexie 最初的意图,但我发现了另一种围绕现有数据库初始化的方法。
出于其他原因,我需要将列的定义存储在单独的数据库中。当我加载现有数据库时,我只是根据该元数据构建正确的版本。
const dbName = 'CustomPeople';
const exists = await Dexie.exists(dbName);
if (exists) {
var db = new Dexie(dbName);
const dynamicDB = await db.open();
const existingVersionNumber = dynamicDB.verno;
const columns = await ExternalDBService.getColumns();
db.close();
db = new Dexie(dbName);
db.version(existingVersionNumber).stores({
People: columns
});
return db.open();
} else {
db = new Dexie(dbName);
db.version(1).stores({
People: []
});
db.open();
}