Signatur
Beschreibung
Die schreibgeschützte Eigenschaft keyPath eines IDBObjectStore gibt an, aus welcher Eigenschaft der gespeicherten Objekte IndexedDB den Primärschlüssel ausliest. Festgelegt wird der Schlüsselpfad einmalig beim Anlegen des Speichers mit IDBDatabase.createObjectStore(name, { keyPath }). Danach lässt er sich nicht mehr ändern, ohne den Speicher zu löschen und neu anzulegen.
Der Wert kann drei Formen haben:
null: Es gibt keinen Inline-Schlüssel. Den Schlüssel übergibt man dann beiadd()/put()als zweites Argument, oder ein Schlüsselgenerator (autoIncrement: true) erzeugt ihn.- String: Ein Pfad zu einer Eigenschaft, z. B.
"id"oder mit Punkt-Notation für verschachtelte Werte, z. B."meta.uuid". - String-Array: Ein zusammengesetzter Schlüssel aus mehreren Eigenschaften, z. B.
["nachname", "vorname"].
Nützlich ist keyPath vor allem für generischen Code wie Export- und Import-Werkzeuge, Migrationen oder Debug-Hilfen. Solcher Code muss wissen, ob Datensätze ihren Schlüssel selbst mitbringen (Inline-Schlüssel) oder ob man ihn separat übergeben muss (Out-of-line-Schlüssel).
Rückgabewert
null, wenn der Speicher Out-of-line-Schlüssel verwendet.Beispiele
Schlüsselpfad beim Anlegen festlegen und auslesen
const request = indexedDB.open('shop', 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const produkte = db.createObjectStore('produkte', { keyPath: 'sku' });
const logs = db.createObjectStore('logs', { autoIncrement: true });
const personen = db.createObjectStore('personen', { keyPath: ['nachname', 'vorname'] });
console.log(produkte.keyPath);
console.log(logs.keyPath);
console.log(personen.keyPath);
};
Generisch speichern – Inline- oder Out-of-line-Schlüssel erkennen
const speichern = (db, storeName, wert, schluessel) =>
new Promise((resolve, reject) => {
const tx = db.transaction(storeName, 'readwrite');
const store = tx.objectStore(storeName);
// Bei Inline-Schlüssel darf KEIN zweites Argument übergeben werden
const req = store.keyPath !== null
? store.put(wert)
: store.put(wert, schluessel);
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
// Nutzung (db aus indexedDB.open):
// await speichern(db, 'produkte', { sku: 'A-100', name: 'Tasse' });
// await speichern(db, 'einstellungen', 'dunkel', 'theme');
Schlüssel eines Datensatzes aus dem keyPath ermitteln (Export-Hilfe)
const wertAmPfad = (obj, pfad) =>
pfad.split('.').reduce((o, teil) => o?.[teil], obj);
const schluesselVon = (store, datensatz) => {
const { keyPath } = store;
if (keyPath === null) return undefined;
return Array.isArray(keyPath)
? keyPath.map((p) => wertAmPfad(datensatz, p))
: wertAmPfad(datensatz, keyPath);
};
// Simulierter Store zum Testen
console.log(schluesselVon({ keyPath: 'meta.uuid' }, { meta: { uuid: 'x1' } }));
console.log(schluesselVon({ keyPath: ['nachname', 'vorname'] }, { vorname: 'Anna', nachname: 'Berg' }));
// Wichtig · Fallstricke
- Schreibgeschützt: Eine Zuweisung an
store.keyPathbleibt ohne Wirkung, im Strict Mode wirft sie einenTypeError. Um den Schlüsselpfad zu ändern, muss man den Speicher in einemonupgradeneeded-Handler löschen und neu anlegen. Die Daten migriert man dabei manuell. - Inline-Schlüssel plus Schlüssel-Argument: Hat der Speicher einen
keyPathund übergibt manput()/add()trotzdem ein zweites Argument, wirft der Aufruf einenDataError. Umgekehrt führt ein fehlender Schlüssel beikeyPath === nullohneautoIncrementebenfalls zu einemDataError. - Ein Array-Schlüsselpfad lässt sich nicht mit
autoIncrement: truekombinieren. Ein leerer String""als Pfad bedeutet: Der gesamte Wert ist der Schlüssel. - Bei Array-Schlüsselpfaden liefert der Getter bei jedem Zugriff eine neue Array-Instanz. Ein Vergleich mit
===ist dann also immerfalse, deshalb besser inhaltlich vergleichen. - Die Eigenschaft wird in allen modernen Browsern und in Web Workern unterstützt. Im privaten Modus mancher Browser ist IndexedDB eingeschränkt.