Удаление нескольких записей в IndexedDB на основе индекса

Я использую IndexedDB, и у меня есть два хранилища объектов: equip (представляет собой различное оборудование, первичный ключ tagNo) и equipParts (представляет части часть оборудования и имеет индекс, который основан на номере метки/серийном номере, первичном ключе seqNo с полем tagNo, которое представляет оборудование, частью которого является эта часть) .

Если я удаляю запись в equip, я хочу удалить все записи в equipParts с tagNo equip ( точно так же, как «где equipParts.tagNo = equip.tagNo»).

Выдержка из моего кода:

var tx = db.transaction(["equip", "equipParts"],"readwrite");
var estore = tx.objectStore("equip");
var pstore = tx.objectStore("equipParts");
var tagIndex = pstore.index("by_tagNo");
var pdestroy = tagIndex.openCursor(IDBKeyRange.only(tagno)); //opens all records bearing the selected tag number
pdestroy.onsuccess = function() {
    var cursor = pdestroy.result;
    if (cursor) {
        if (cursor.value.tagNo == tagno) {
            pstore.delete(cursor.value.seqNo); //I guess I'm wrong here
        }
        cursor.continue;
    }
}
pdestroy.onerror = function() {
    alert("Deletion attempt NG");
}
var ereq = estore.delete(tagno);
ereq.onsuccess = function(e) {
    alert("Form deletion OK");
    window.location = "index.html";
}
ereq.onerror = function(e) {
    alert("Form deletion NG");
    window.location = "index.html";
}
db.close();

Проблема в том, что удаляется только запись в equip; записи в equipParts остаются там. Есть ли способ удалить несколько записей в хранилище объектов IndexedDB на основе неуникального индекса (который может быть первичным ключом хранилища родительских объектов)?


person user2727708    schedule 04.09.2013    source источник


Ответы (3)


Вы должны получить первичные ключи для удаления записей.

var pdestroy = tagIndex.openKeyCursor(IDBKeyRange.only(tagno)); 
pdestroy.onsuccess = function() {
  var cursor = pdestroy.result;
  if (cursor) {
      pstore.delete(cursor.primaryKey);
      cursor.continue();
  }
}

Альтернативно, но неэффективно

var pdestroy = tagIndex.openCursor(IDBKeyRange.only(tagno)); 
pdestroy.onsuccess = function() {
  var cursor = pdestroy.result;
  if (cursor) {
      cursor.delete();
      cursor.continue();
  }
}
person Kyaw Tun    schedule 05.09.2013
comment
Почему второй неэффективен? - person Frank Schwieterman; 27.11.2013
comment
openCursor возвращает IDBCursorWithValue, что требует чтения значения записи, тогда как первый возвращает IDBCursor без значения записи. - person Kyaw Tun; 27.11.2013
comment
Спасибо. Верно ли, что только последний выполняет полное удаление в рамках одной и той же транзакции? - person Frank Schwieterman; 27.11.2013
comment
Удаление записей при открытом курсоре вызывает ошибку в Safari. Курсор станет нулевым, даже если есть дополнительные совпадающие записи. Надежнее получить все первичные ключи, а затем вызвать IDBObjectStore.delete() для каждого из них. - person cleong; 14.05.2018
comment
Имейте в виду, что вы не можете вызывать delete() (или IDBCursor.update()) для курсоров, полученных от IDBIndex.openKeyCursor(). Для таких нужд вы должны использовать вместо этого IDBIndex.openCursor(). - person Ehsan Chavoshi; 02.03.2021
comment
я не понимаю, как оператор cursor.continue() работает без цикла @KyawTun - person datdinhquoc; 23.06.2021
comment
кажется, cursor.continue() снова вызовет запрос .onsuccess - person datdinhquoc; 23.06.2021
comment
@datdinhquoc Вы правы, он создаст новый запрос, но использует тот же источник, поэтому он вызовет тот же обратный вызов onsuccess, где был вызван continue. - person Kyaw Tun; 24.06.2021

Я удалил несколько записей, принадлежащих индексу, таким образом, используя idb:

    var tx = idb.transaction("MyObjectStore", 'readwrite');
    var index = tx.store.index('my_relid_idx');
    var pdestroy = index.openCursor(RelID);
    pdestroy.then(async cursor => {
        while (cursor) {
            cursor.delete();
            cursor = await cursor.continue();
        }
    })
person Ehsan Chavoshi    schedule 02.03.2021
comment
это использует jakearchibald/idb, а не vanilla IndexedDB API - person datdinhquoc; 23.06.2021

Я нашел самый простой подход с этим

index.iterateCursor(IDBKeyRange, (cursor) => {
  if(cursor){
    cursor.delete();
    cursor.continue();
  }
});

таким образом, если у вас есть асинхронная функция, вы можете просто использовать

await index.iterateCursor...

и ждать обещания с другой стороны

person sebas sierra    schedule 16.10.2019
comment
это работает, но почему бы не использовать метод «удалить» непосредственно в IDBIndex, как .get и .getAll - person datdinhquoc; 23.06.2021
comment
обновление: я не вижу метод iterateCursor, задокументированный в IDBIndex; я пробовал еще раз, не работает @sebas - person datdinhquoc; 23.06.2021
comment
.iterateCursor кажется старой функцией?: github.com/jakearchibald/idb/search?q=iterateCursor - person datdinhquoc; 23.06.2021