Deleting all records in indexedDB object store for a specific index value

喜欢而已 提交于 2021-01-27 11:53:46

问题


For an object store with an array key of [a,b] where a is also an index, is there a more efficient way to delete all records for a specific value of a than opening a cursor on the index a and deleting each record as step through the cursor?

Is there a way to define a key range for an index only, or just on a and leave b open to any value, such that can delete all records for that key range?

In this particular case, a is a positive integer excluding zero and b is a positive integer including zero. Would a key range from [n,0] to [n+1,0] be guaranteed to return all keys for equivalent to index a=n regardless of the value of b? For example, IDBKeyRange.bound( [2,0], [3,0], false, true) would return all keys for index a=2?

The above key range works for my test cases, but I'd like to know how to handle the situation if b wasn't an integer, making it sort of a special case.

It appears that the following would not work because it would delete only a record with a key of 2. Is there a method like this for a general case?

i = transaction.objectStore( name ).index( 'a' );
i.delete( 2 );

Thank you.

As I learned more and looked over code below that is generating the desired result, I'm not sure anymore why it is working. The key is compound [ topic, note ] and k is set to only the topic value. So, no key in n should match k, should it?

I don't understand why n.openCursor( k ) returned any records to work on, since none have a simple key. Is k being treated as the key of the records or the index value?

T = DB_open.base.transaction( ['notes'], 'readwrite' ),
o = T.objectStore( 'notes' ),
k = IDBKeyRange.only( topic_value );
n = T.objectStore( 'notes' ).index( 'topic' );

n.openCursor( k ).onsuccess = ( e ) =>  { /* stepped through cursor */ };

It appears that what I wasn't understanding is that the key parameter for an index is not the key of the actual record but the key of the index, here the topic value. For read operations and cursors, that works fine; but there is not a delete method on an index, such as a deleteAll equivalent to getAll.

I think I must have understood this several months ago when I wrote the cursor code but now got myself confused in trying to delete a set of records for a specific index value without opening a cursor.


回答1:


It appears that what I wasn't understanding is that the key parameter for an index is not the key of the actual record but the key of the index, here the topic value. For read operations and cursors, that works fine; but there is not a delete method on an index, such as a deleteAll equivalent to getAll.

You are correct, key is the index key. And there is no single command to say "delete every record matching a certain key or key range in an index". Here is some discussion about this - my interpretation is that there isn't a great argument against that functionality existing, but it's a rare enough use case that it's just sat there as an unimplemented feature request.

However if the primary key is an compound key and the first entry in the compound key is the field you want to filter on, you can use a KeyRange and pass it to IDBObjectStore.delete like you suggested:

In this particular case, a is a positive integer excluding zero and b is a positive integer including zero. Would a key range from [n,0] to [n+1,0] be guaranteed to return all keys for equivalent to index a=n regardless of the value of b? For example, IDBKeyRange.bound( [2,0], [3,0], false, true) would return all keys for index a=2?

Yes, that would work.

You can play around with it an see for yourself too:

var range = IDBKeyRange.bound( [2,0], [3,0], false, true);
console.log(range.includes([2, -1])); // false
console.log(range.includes([2, 0])); // true
console.log(range.includes([2, 100])); // true
console.log(range.includes([2, Infinity])); // true
console.log(range.includes([3, 0])); // false

Just for fun... you could also define your key range like this:

var range = IDBKeyRange.bound( [2,0], [2,""], false, true);

since numbers sort before strings. There's a bunch of other ways you could write the same thing. It all comes down to how cross-type comparisons are done in the IndexedDB spec. As soon as you have arrays or multiple types, things get interesting.



来源:https://stackoverflow.com/questions/55927915/deleting-all-records-in-indexeddb-object-store-for-a-specific-index-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!