在已有的 objectStore 上创建索引

vol*_*lna 9 javascript indexeddb

作为基本设置的示例,创建了一个索引。

db.onupgradeneeded = function(event) {
   var db = event.target.result;
   var store = db.createObjectStore('name', { keyPath: 'id' });
   store.createIndex('by name', 'name', { unique: false });
};
Run Code Online (Sandbox Code Playgroud)

问题:是否可以在相同的索引上创建/附加更多objectStore索引future versionupdate

因为如果我尝试:

db.onupgradeneeded = function(event) {
   var db = event.target.result;
   var store = db.createObjectStore('name', { keyPath: 'id' });

   store.createIndex('by newName', 'newName', { unique: false });
};
Run Code Online (Sandbox Code Playgroud)

它会抛出一个错误current objectStore does already exist。如果我尝试使用事务创建商店引用:

db.onupgradeneeded = function(event) {
   var db = event.target.result;
   var store = db.transaction('name', 'readwrite').objectStore('name');

   store.createIndex('by newName', 'newName', { unique: false });
};
Run Code Online (Sandbox Code Playgroud)

它抛出了那个version change transaction is currently running

Jos*_*osh 16

对的,这是可能的。一开始可能会有点混乱。您希望通过在 onupgradeneeded 中为您创建的隐式事务来获取现有的对象存储。这是一个versionchange类型的事务,基本上类似于读写事务,但特定于 onupgradeneeded 处理程序函数。

像这样的东西:

var request = indexedDB.open(name, oldVersionPlusOne);
request.onupgradeneeded = myOnUpgradeNeeded;

function myOnUpgradeNeeded(event) {
  // Get a reference to the request related to this event
  // @type IDBOpenRequest (a specialized type of IDBRequest)
  var request = event.target;

  // Get a reference to the IDBDatabase object for this request
  // @type IDBDatabase
  var db = request.result;

  // Get a reference to the implicit transaction for this request
  // @type IDBTransaction
  var txn = request.transaction;

  // Now, get a reference to the existing object store
  // @type IDBObjectStore
  var store = txn.objectStore('myStore');

  // Now, optionally inspect index names, or create a new index
  console.log('existing index names in store', store.indexNames);

  // Add a new index to the existing object store
  store.createIndex(...);
}
Run Code Online (Sandbox Code Playgroud)

您还需要注意增加版本,以确保调用 onupgradeneeded 处理函数,并表示您的架构(基本上是表、索引和事物的属性集)在新版本中已更改。

您还需要重写该函数,以便仅根据版本创建或进行更改。您可以使用event.oldVersion来帮助解决此问题,或类似的事情db.objectStoreNames.contains

像这样的东西:

function myOnUpgradeNeeded(event) {
  var is_new_db = isNaN(event.oldVersion) || event.oldVersion === 0;
  if(is_new_db) {
    var db = event.target.result;
    var store = db.createObjectStore(...);
    store.createIndex('my-initial-index');
    // Now that you decided you want a second index, you also need 
    // to do this for brand new databases
    store.createIndex('my-second-new-index');
  }

  // But if the database already exists, we are not creating things, 
  // instead we are modifying the existing things to get into the 
  // new state of things we want
  var is_old_db_not_yet_current_version = !isNaN(event.oldVersion) && event.oldVersion < 2;
  if(is_old_db_not_yet_current_version) {
    var txn = event.target.transaction;
    var store = txn.objectStore('store');
    store.createIndex('my-second-new-index');
  }
}
Run Code Online (Sandbox Code Playgroud)

请密切注意我使用event.target.transaction而不是db.transaction(...). 这些根本不是同一件事。一个引用现有事务,一个创建一个新事务。

最后,此外,这是我的个人规则,而不是正式的编码要求,您永远不应该db.transaction()在 onupgradeneeded 内部使用。升级时坚持修改架构,并在架构之外进行所有数据更改。