Start · Sprachen · JavaScript · Referenz · IDBDatabase.createObjectStore()

IDBDatabase.createObjectStore()

Methode

Erstellt innerhalb einer <code>versionchange</code>-Transaktion einen neuen Object Store in der Datenbank und gibt ihn als <code>IDBObjectStore</code> zurück.

seit JavaScript Baseline: alle Browser (IndexedDB 2.0) Kategorie: webapi

Signatur

IDBDatabase.prototype.createObjectStore(name, options)

Beschreibung

Mit createObjectStore() legt man in einer IndexedDB-Datenbank einen neuen Object Store an, also ungefähr das, was in einer relationalen Datenbank eine Tabelle ist. Jeder Store hat einen eindeutigen Namen. Man kann festlegen, wie die Schlüssel der Datensätze entstehen: über einen Schlüsselpfad (keyPath) im gespeicherten Objekt, über einen automatisch hochgezählten Schlüsselgenerator (autoIncrement) oder über beides zusammen.

Die Methode lässt sich nur innerhalb einer versionchange-Transaktion aufrufen. In der Praxis heißt das: nur im Handler des Events upgradeneeded, das indexedDB.open() auslöst, wenn die Datenbank neu ist oder eine höhere Versionsnummer angefordert wird. Außerhalb davon wirft der Aufruf eine InvalidStateError-DOMException.

Der zurückgegebene IDBObjectStore gehört zur laufenden Upgrade-Transaktion. Auf ihm kann man sofort mit createIndex() Indizes anlegen oder mit add()/put() erste Daten einspielen, zum Beispiel für eine Migration.

Welche Schlüssel-Strategie man wählt, hängt vom Datenmodell ab. Haben die Objekte eine natürliche eindeutige ID, nimmt man keyPath. Sollen fortlaufende IDs automatisch vergeben werden, kombiniert man keyPath mit autoIncrement: true. Ohne beide Optionen spricht man von Out-of-line-Keys: Den Schlüssel muss man dann bei jedem add()/put() als zweites Argument selbst übergeben.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Name des neuen Object Stores. Er muss in der Datenbank eindeutig sein, ein leerer String ist erlaubt.
$options { keyPath?: string | string[] | null, autoIncrement?: boolean } { keyPath: null, autoIncrement: false } Optionales Konfigurationsobjekt. keyPath: Pfad zur Schlüssel-Eigenschaft im gespeicherten Objekt, z. B. "id" oder "user.email", oder ein Array von Pfaden für einen zusammengesetzten Schlüssel. autoIncrement: Bei true wird ein Schlüsselgenerator verwendet, der fortlaufende Zahlen vergibt.

Rückgabewert

Typ
IDBObjectStore
Beschreibung
Der neu angelegte Object Store. Er ist an die aktuelle versionchange-Transaktion gebunden.

Beispiele

Store mit Schlüsselpfad und Index anlegen

const request = indexedDB.open('shop', 1);

request.addEventListener('upgradeneeded', (event) => {
  const db = event.target.result;
  // Produkte werden über ihre Eigenschaft "sku" identifiziert
  const store = db.createObjectStore('products', { keyPath: 'sku' });
  store.createIndex('byCategory', 'category', { unique: false });
  console.log('Store angelegt:', store.name, store.keyPath);
});

request.addEventListener('success', () => {
  console.log('Datenbank bereit');
});
Store angelegt: products sku Datenbank bereit

Automatisch hochgezählte IDs und Startdaten

const request = indexedDB.open('todo-app', 1);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const todos = db.createObjectStore('todos', {
    keyPath: 'id',
    autoIncrement: true
  });
  // Startdaten direkt in der Upgrade-Transaktion einspielen
  todos.add({ title: 'IndexedDB lernen', done: false });
  todos.add({ title: 'Einkaufen', done: true });
};

request.onsuccess = (event) => {
  const db = event.target.result;
  const getAll = db.transaction('todos').objectStore('todos').getAll();
  getAll.onsuccess = () => console.log(getAll.result);
};
[{ title: 'IndexedDB lernen', done: false, id: 1 }, { title: 'Einkaufen', done: true, id: 2 }]

Versionsmigration mit Existenzprüfung

const openDb = () => new Promise((resolve, reject) => {
  const request = indexedDB.open('notes', 2);

  request.onupgradeneeded = (event) => {
    const db = request.result;
    const { oldVersion } = event;

    if (oldVersion < 1) {
      db.createObjectStore('notes', { keyPath: 'id', autoIncrement: true });
    }
    if (oldVersion < 2 && !db.objectStoreNames.contains('settings')) {
      // Out-of-line-Keys: Der Schlüssel wird beim put() mitgegeben
      db.createObjectStore('settings');
    }
  };

  request.onsuccess = () => resolve(request.result);
  request.onerror = () => reject(request.error);
});

const db = await openDb();
console.log([...db.objectStoreNames]);
['notes', 'settings']

// Wichtig · Fallstricke

  • InvalidStateError: Die Methode wurde außerhalb einer versionchange-Transaktion aufgerufen, etwa im success-Handler. Soll ein neuer Store dazukommen, muss man die Datenbank mit einer höheren Versionsnummer öffnen.
  • ConstraintError: Ein Store mit diesem Namen existiert bereits. Vorher mit db.objectStoreNames.contains(name) prüfen.
  • InvalidAccessError: autoIncrement: true zusammen mit einem leeren String oder einem Array als keyPath ist nicht erlaubt.
  • SyntaxError: Der keyPath ist kein gültiger Schlüsselpfad.
  • TransactionInactiveError: Die Upgrade-Transaktion ist schon beendet, zum Beispiel weil der Aufruf in einem asynchronen Callback wie setTimeout oder nach einem await auf ein fremdes Promise steht.
  • Schlüsselpfad und autoIncrement lassen sich später nicht mehr ändern. Dafür muss man den Store mit deleteObjectStore() löschen und neu anlegen, und die Daten gehen dabei verloren, wenn man sie nicht vorher sichert.
  • Ein Schlüsselgenerator setzt seinen Zähler nie zurück, auch nicht nach clear().
  • Die Methode wird von allen modernen Browsern unterstützt. Im privaten Modus mancher Browser (vor allem ältere Firefox-Versionen) ist IndexedDB eingeschränkt oder gar nicht verfügbar.