Signatur
Beschreibung
Die Eigenschaft unique eines IDBIndex-Objekts sagt, ob der Index beim Anlegen mit der Option { unique: true } erstellt wurde. Ist der Wert true, dürfen zwei Datensätze im zugehörigen Object Store für den indizierten Schlüsselpfad nicht denselben Wert haben. Ist er false (Standard), sind doppelte Indexschlüssel erlaubt.
Den Wert legt man einmalig über IDBObjectStore.prototype.createIndex(name, keyPath, { unique }) fest. Das geht nur innerhalb eines upgradeneeded-Handlers, also in einer versionchange-Transaktion. Danach lässt er sich nicht mehr ändern. Soll sich die Eindeutigkeit ändern, musst du den Index mit deleteIndex() löschen und in einer neuen Datenbankversion neu anlegen.
Praktisch hilft unique vor allem beim Prüfen des Schemas zur Laufzeit, bei Migrationen und beim Debuggen. So erkennst du etwa, ob ein E-Mail-Index wirklich eindeutig ist. Ist das der Fall, schlägt ein add() oder put() mit einem doppelten Wert mit einem ConstraintError fehl.
Rückgabewert
true, wenn der Index keine doppelten Schlüssel zulässt, sonst false.Beispiele
Eindeutigen Index anlegen und prüfen
const request = indexedDB.open('shop', 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const store = db.createObjectStore('kunden', { keyPath: 'id', autoIncrement: true });
const emailIndex = store.createIndex('email', 'email', { unique: true });
const stadtIndex = store.createIndex('stadt', 'stadt'); // unique: false (Standard)
console.log(emailIndex.unique);
console.log(stadtIndex.unique);
};
Schema aller Indizes zur Laufzeit ausgeben
const openDb = (name) => new Promise((resolve, reject) => {
const req = indexedDB.open(name);
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
const db = await openDb('shop');
const store = db.transaction('kunden', 'readonly').objectStore('kunden');
for (const name of store.indexNames) {
const index = store.index(name);
console.log(`${index.name}: keyPath=${index.keyPath}, unique=${index.unique}`);
}
ConstraintError bei eindeutigem Index abfangen
const addKunde = (db, kunde) => new Promise((resolve, reject) => {
const tx = db.transaction('kunden', 'readwrite');
const store = tx.objectStore('kunden');
const req = store.add(kunde);
req.onsuccess = () => resolve(req.result);
req.onerror = (event) => {
event.preventDefault(); // verhindert Abbruch der Transaktion
const unique = store.index('email').unique;
reject(new Error(`${req.error.name} (email unique=${unique})`));
};
});
try {
await addKunde(db, { email: 'anna@example.com', stadt: 'Berlin' });
await addKunde(db, { email: 'anna@example.com', stadt: 'Hamburg' });
} catch (err) {
console.log(err.message);
}
// Wichtig · Fallstricke
- Nur lesbar: Eine Zuweisung wie
index.unique = truehat keine Wirkung und wirft im Strict Mode einenTypeError. Ändern lässt sich die Eindeutigkeit nur, indem du den Index in einemupgradeneeded-Handler löschst und neu anlegst. - Bestehende Duplikate: Enthält der Object Store beim Anlegen eines eindeutigen Index schon doppelte Werte, schlägt
createIndex()fehl. Die Upgrade-Transaktion wird dann mit einemConstraintErrorabgebrochen. - Zusammen mit
multiEntry: BeimultiEntry: truegilt die Eindeutigkeit für jedes einzelne Array-Element über alle Datensätze hinweg. Doppelte Werte innerhalb desselben Arrays werden nur einmal indiziert. - Datensätze, bei denen der Schlüsselpfad fehlt oder keinen gültigen Schlüssel ergibt, kommen gar nicht in den Index und verletzen die Eindeutigkeit deshalb nicht.
- Kompatibilität: Wird in allen modernen Browsern und in Web Workern unterstützt. In privaten Fenstern mancher Browser ist IndexedDB eingeschränkt.