最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Create index on already existing objectStore - Stack Overflow

programmeradmin4浏览0评论

As an example on basic setup one index is created.

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

Question: Is it possible to create/append more indexes to the same objectStore on the future versionupdate?

Since if I try:

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

   store.createIndex('by newName', 'newName', { unique: false });
};

It throws an error that current objectStore does already exist. An if I try to create store reference using transaction:

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

   store.createIndex('by newName', 'newName', { unique: false });
};

It throws that version change transaction is currently running

As an example on basic setup one index is created.

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

Question: Is it possible to create/append more indexes to the same objectStore on the future versionupdate?

Since if I try:

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

   store.createIndex('by newName', 'newName', { unique: false });
};

It throws an error that current objectStore does already exist. An if I try to create store reference using transaction:

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

   store.createIndex('by newName', 'newName', { unique: false });
};

It throws that version change transaction is currently running

Share Improve this question asked May 5, 2018 at 20:47 volnavolna 2,6104 gold badges31 silver badges68 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 20

Yes it is possible. It can be a bit confusing at first. You want to get the existing object store via the implicit transaction created for you within onupgradeneeded. This is a transaction of type versionchange which is basically like a readwrite transaction but specific to the onupgradeneeded handler function.

Something like this:

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(...);
}

You also will want to take care to increment the version so as to guarantee the onupgradeneeded handler function is called, and to represent that your schema (basically the set of tables and indices and properties of things) has changed in the new version.

You will also need to rewrite the function so that you only create or make changes based on the version. You can use event.oldVersion to help with this, or things like db.objectStoreNames.contains.

Something like this:

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');
  }
}

Pay close attention to the fact that I used event.target.transaction instead of db.transaction(...). These are not at all the same thing. One references an existing transaction, and one creates a new one.

Finally, and in addition, a personal rule of mine and not a formal coding requirement, you should never be using db.transaction() from within onupgradeneeded. Stick to modifying the schema when doing upgrades, and do all data changes outside of it.

发布评论

评论列表(0)

  1. 暂无评论