Start · Sprachen · JavaScript · Referenz · IDBObjectStore.createIndex()

IDBObjectStore.createIndex()

Methode

Erstellt einen neuen Index auf einem Objektspeicher und gibt das zugehörige <code>IDBIndex</code>-Objekt zurück; nur während eines <code>versionchange</code>-Vorgangs erlaubt.

seit JavaScript Baseline: alle modernen Browser Kategorie: webapi

Signatur

IDBObjectStore.prototype.createIndex(indexName, keyPath, options)

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

Typ
IDBIndex
Beschreibung
Das neu angelegte 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');
["email", "nachname"] 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));
["IndexedDB-Grundlagen", "Promises verstehen"]

// Wichtig · Fallstricke

  • Nur in upgradeneeded: Außerhalb einer versionchange-Transaktion wirft der Aufruf einen InvalidStateError. Das passiert auch, wenn die Transaktion schon beendet ist, zum Beispiel nach einem await auf etwas anderes als eine IndexedDB-Anfrage.
  • ConstraintError: Tritt auf, wenn es bereits einen Index mit diesem Namen gibt. Prüfe das vorher mit store.indexNames.contains(name).
  • SyntaxError: Tritt bei einem ungültigen keyPath auf. InvalidAccessError kommt, wenn multiEntry: true mit einem Array-keyPath kombiniert wird.
  • Bestehende Daten mit unique: true: Enthält der Objektspeicher schon doppelte Werte, schlägt das Upgrade fehl. Die Transaktion wird dann mit einem ConstraintError abgebrochen, 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 locale gibt es nur in Firefox.