Dexie.js自动增量主键 - 是否重置?如何重置?

时间:2018-03-09 09:47:45

标签: javascript indexeddb dexie

在Dexie.js中,您可以使用自动递增键创建商店

    let db = new Dexie("nav_api");
    db.version(1).stores({
        jobs: '++id, json'
    });

所以为了测试,我通过db.jobs.put({json: '[]'})在数据库中创建了14个对象,并且所有键都按预期出现,从1到14开始。然后删除了一些后来的db.jobs.where('id').above(6).delete() ,并在db中添加了另一个,其索引为15。

有没有办法将索引重置为0?我正在使用它进行排序,我不确定当值变得非常大时会发生什么 - 它最终会回绕到0吗?

另一方面,它也可能不是我需要担心的事情。取决于'++ id'字段的高度,并且我假设它将达到数十亿,这将是许多年(许多生命周期)之前需要担心的事情。所以也许我应该忽略它。

[编辑] 我尝试清除表db.jobs.clear(),然后在表中添加一个新行,但之后又使用了下一个索引。我找不到完全删除表的方法,但是我可以完全删除整个数据库,但我真的不想这样做。

2 个答案:

答案 0 :(得分:1)

The IndexedDB spec has more info.

你可能不会达到上限:

  

当前数字始终为小于或等于2 53 (9007199254740992)+ 1的正整数。

除了删除对象存储并重新创建它之外,没有办法重置它:

  

密钥生成器的当前编号永远不会减少,除非由于数据库操作被还原。从对象库中删除记录永远不会影响对象库的密钥生成器。甚至清除对象库中的所有记录(例如使用clear()方法)也不会影响对象库的密钥生成器的当前编号。

答案 1 :(得分:0)

已接受的答案仅部分解决了问题,并未以代码形式提供实际的问题解决方案。在我看来,不需要自动递增的整数就不是一个好主意。当然,人们将需要大量的数据,但是大量的数据可能会激怒用户,特别是如果用户问自己之前的ID在哪里。

我主要是从Dexie-Developer dfahlander 复制过来的this script,并对其进行更改以实现所需的功能。请注意,来回克隆数据库可能需要很长时间才能运行,具体取决于数据库的大小。 bulkAdd没有包装在事务中,因此在错误时脚本可能会中断。 那是说我必须警告您在执行此功能之前进行备份。

function refreshIndices(database){

  const databases = [database, database+'_temp'];
  // Loop 2 times - move database forth and back
  (function next(cnt, max){
    if(cnt++ >= max){ doSomething(); return;}
    // ! turns 1 into 0 and vice-versa / + turns boolean into integer
    var sdb = new Dexie(databases[cnt-1]),
        ddb = new Dexie(databases[+!(cnt-1)]);

    sdb.open().then(()=>{
        // Clone scheme
        const schema = sdb.tables.reduce((result,table)=>{
          result[table.name] = (
            [table.schema.primKey]
            .concat(table.schema.indexes)
            .map(indexSpec => indexSpec.src)
            ).toString();
          return result;
        }, {});
        ddb.version(sdb.verno).stores(schema);

        // Clone Data and delete source-database
        return sdb.tables.reduce(
          (result, table) => result
            .then(() => table.toArray())
            .then(rows => ddb.table(table.name).bulkAdd(rows) ),
          Promise.resolve()     
        ).then((x)=>{ sdb.delete(); ddb.close(); next(cnt,max); })
    })
  })(0, databases.length);
}

必须使用要克隆的数据库名称作为字符串来调用此函数。 (即refreshIndices('dbname'))数据库必须存在。该函数迭代2次。第一次运行时,源数据库被克隆到临时数据库中,然后源数据库被删除。完成后,该功能将再次运行,并将临时数据库克隆到源数据库中,然后删除该临时数据库。不会留下任何开销。

出于调试目的,我将更改

.then(rows => ddb.table(table.name).bulkAdd(rows) )

.then((rows) => { 
    console.log("Cloning "+table.name);
    ddb.table(table.name).bulkAdd(rows)
}) )

此功能应与Dexie.js一起使用。还可以通过Developer Tools (Chrome) => Application => IndexedDB => __dbnames => Refresh来创建数据库。