重命名本地PouchDB且无需重建索引的可行方案咨询
PouchDB本地库免索引重建重命名解决方案
核心思路是直接操作浏览器底层IndexedDB实例,批量迁移全量数据和索引数据,同步更新PouchDB内部配置,全程不会触发索引重建,操作耗时仅和数据库总大小正相关,远快于重新构建索引。
具体操作步骤
第一步:收集旧库关联的所有IndexedDB名称
初始化旧名称的PouchDB实例,读取两份内部本地配置文档:_local/_pouch_dependentDbs和_local/mrviews,收集完整的关联库列表:主库_pouch_<旧库名>+ 所有_pouch_<旧库名>-mrview-<哈希值>格式的索引库。第二步:底层IndexedDB批量迁移
不需要通过PouchDB上层API同步,直接调用原生IndexedDB API对每一个关联库做全量迁移:// 单IndexedDB迁移方法 async function migrateIDB(oldName, newName) { return new Promise((resolve, reject) => { // 打开旧库读取全量数据 const oldReq = indexedDB.open(oldName); oldReq.onsuccess = (e) => { const oldDB = e.target.result; const transaction = oldDB.transaction(oldDB.objectStoreNames, 'readonly'); const allData = {}; // 遍历所有对象存储拉取数据 Array.from(oldDB.objectStoreNames).forEach(storeName => { const store = transaction.objectStore(storeName); store.getAll().onsuccess = (ev) => { allData[storeName] = ev.target.result; }; }); transaction.oncomplete = () => { oldDB.close(); // 创建新库,复用旧库的版本号和对象存储配置 const newReq = indexedDB.open(newName, oldDB.version); newReq.onupgradeneeded = (ev) => { const newDB = ev.target.result; // 完全复制旧库的对象存储、索引配置 Array.from(oldDB.objectStoreNames).forEach(storeName => { const oldStore = transaction.objectStore(storeName); const newStore = newDB.createObjectStore(storeName, { keyPath: oldStore.keyPath, autoIncrement: oldStore.autoIncrement }); // 复制所有索引配置 Array.from(oldStore.indexNames).forEach(idxName => { const idx = oldStore.index(idxName); newStore.createIndex(idxName, idx.keyPath, { unique: idx.unique, multiEntry: idx.multiEntry }); }); }); }; newReq.onsuccess = (ev) => { const newDB = ev.target.result; // 写入所有旧数据 const writeTrans = newDB.transaction(newDB.objectStoreNames, 'readwrite'); Object.keys(allData).forEach(storeName => { const store = writeTrans.objectStore(storeName); allData[storeName].forEach(item => store.put(item)); }); writeTrans.oncomplete = () => { newDB.close(); // 删除旧库(可选,验证完成后再执行) indexedDB.deleteDatabase(oldName); resolve(); }; writeTrans.onerror = reject; }; newReq.onerror = reject; }; }; oldReq.onerror = reject; }); }遍历之前收集到的所有旧关联库,把库名中的
<旧库名>替换为<新库名>,逐个调用上面的方法完成迁移。第三步:更新新库内部配置
初始化新名称的PouchDB实例,把之前读取的两份本地配置文档中,所有出现旧库名的字段全部替换为新库名,再写入新PouchDB实例的本地文档中。
注意事项
- 操作前建议先做用户本地数据备份,避免操作失误导致数据丢失
- 整个迁移过程中不要对旧库、新库执行任何PouchDB读写、查询操作,避免数据不一致
- 迁移完成后再初始化新的PouchDB实例,此时调用视图查询会直接复用已有索引,不需要重建
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

