Signatur
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
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');
});
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);
};
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]);
// Wichtig · Fallstricke
InvalidStateError: Die Methode wurde außerhalb einerversionchange-Transaktion aufgerufen, etwa imsuccess-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 mitdb.objectStoreNames.contains(name)prüfen.InvalidAccessError:autoIncrement: truezusammen mit einem leeren String oder einem Array alskeyPathist nicht erlaubt.SyntaxError: DerkeyPathist kein gültiger Schlüsselpfad.TransactionInactiveError: Die Upgrade-Transaktion ist schon beendet, zum Beispiel weil der Aufruf in einem asynchronen Callback wiesetTimeoutoder nach einemawaitauf ein fremdes Promise steht.- Schlüsselpfad und
autoIncrementlassen sich später nicht mehr ändern. Dafür muss man den Store mitdeleteObjectStore()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.