Signatur
Beschreibung
Mit createIndex() legst du auf einem IDBObjectStore einen Index an. Über einen Index findest du Datensätze nach einer anderen Eigenschaft als dem Primärschlüssel, z. B. Nutzer nach E-Mail-Adresse oder Bestellungen nach Datum. Die Methode gibt sofort ein IDBIndex-Objekt zurück, über das du später mit get(), getAll(), count() oder openCursor() abfragen kannst.
Indizes gehören zum Datenbankschema. Deshalb darfst du createIndex() nur innerhalb einer versionchange-Transaktion aufrufen, also im upgradeneeded-Handler von indexedDB.open(). Willst du einer bestehenden Datenbank einen Index hinzufügen, erhöhst du die Versionsnummer und holst dir den Objektspeicher über event.target.transaction.objectStore(name).
Mit dem Optionsobjekt bestimmst du das Verhalten: unique: true verlangt eindeutige Werte (etwa bei E-Mail-Adressen), und multiEntry: true legt bei einem Array-Wert für jedes Element einen eigenen Indexeintrag an, was für Tags oder Kategorien praktisch ist.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $indexName Pflicht | string | Name des Index. Er muss innerhalb des Objektspeichers eindeutig sein, auch leere Zeichenketten sind erlaubt. | |
| $keyPath Pflicht | string | string[] | Schlüsselpfad, über den der Index seine Werte aus jedem Datensatz liest. Verschachtelte Eigenschaften schreibst du mit Punkt, z. B. 'adresse.plz'. Ein Array ergibt einen zusammengesetzten Index aus mehreren Eigenschaften. |
|
| $options | { unique?: boolean, multiEntry?: boolean } | { unique: false, multiEntry: false } | unique: Doppelte Indexwerte sind dann nicht erlaubt. multiEntry: Bei Array-Werten wird pro Element ein Eintrag angelegt. Mit einem Array als keyPath ist diese Option nicht kombinierbar. locale gibt es nur in Firefox (nicht standardisiert). |
Rückgabewert
IDBIndex-Objekt.Beispiele
Schema mit eindeutigem E-Mail-Index anlegen
const request = indexedDB.open('shop', 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const kunden = db.createObjectStore('kunden', { keyPath: 'id', autoIncrement: true });
// Eindeutiger Index: zwei Kunden mit derselben E-Mail sind nicht möglich
kunden.createIndex('email', 'email', { unique: true });
// Normaler Index für Suchen nach Nachnamen
kunden.createIndex('nachname', 'nachname');
console.log([...kunden.indexNames]);
};
request.onsuccess = () => console.log('Datenbank bereit');
Nachträglich einen Index per Versions-Upgrade hinzufügen
const request = indexedDB.open('shop', 2);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const tx = event.target.transaction; // die laufende versionchange-Transaktion
if (event.oldVersion < 1) {
db.createObjectStore('kunden', { keyPath: 'id', autoIncrement: true });
}
if (event.oldVersion < 2) {
const kunden = tx.objectStore('kunden');
if (!kunden.indexNames.contains('plz')) {
// verschachtelter Schlüsselpfad
kunden.createIndex('plz', 'adresse.plz');
}
}
};
multiEntry-Index für Tags und Abfrage über den Index
const openDb = () => new Promise((resolve, reject) => {
const req = indexedDB.open('blog', 1);
req.onupgradeneeded = () => {
const store = req.result.createObjectStore('artikel', { keyPath: 'id' });
store.createIndex('tags', 'tags', { multiEntry: true });
};
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
const db = await openDb();
const tx = db.transaction('artikel', 'readwrite');
const store = tx.objectStore('artikel');
store.put({ id: 1, titel: 'IndexedDB-Grundlagen', tags: ['js', 'datenbank'] });
store.put({ id: 2, titel: 'Promises verstehen', tags: ['js'] });
const req = store.index('tags').getAll('js');
req.onsuccess = () => console.log(req.result.map((a) => a.titel));
// Wichtig · Fallstricke
- Nur in
upgradeneeded: Außerhalb einerversionchange-Transaktion wirft der Aufruf einenInvalidStateError. Das passiert auch, wenn die Transaktion schon beendet ist, zum Beispiel nach einemawaitauf etwas anderes als eine IndexedDB-Anfrage. ConstraintError: Tritt auf, wenn es bereits einen Index mit diesem Namen gibt. Prüfe das vorher mitstore.indexNames.contains(name).SyntaxError: Tritt bei einem ungültigenkeyPathauf.InvalidAccessErrorkommt, wennmultiEntry: truemit einem Array-keyPathkombiniert wird.- Bestehende Daten mit
unique: true: Enthält der Objektspeicher schon doppelte Werte, schlägt das Upgrade fehl. Die Transaktion wird dann mit einemConstraintErrorabgebrochen, der Aufruf selbst wirft aber nicht sofort. - Datensätze, deren Schlüsselpfad keinen gültigen Schlüssel liefert (fehlend,
null,boolean), nimmt der Index nicht auf. Sie tauchen bei Abfragen über den Index nicht auf. - Die Methode wird von allen modernen Browsern unterstützt, in Web Workers ebenfalls. Die Option
localegibt es nur in Firefox.