Arbeiten mit IndexedDB

Eine der interessanteren Entwicklungen in Bezug auf Webstandards ist in letzter Zeit die Spezifikation für indizierte Datenbanken (IndexedDB). Für eine lustige Zeit können Sie die Spezifikation selbst lesen. In diesem Tutorial werde ich diese Funktion erklären und Ihnen hoffentlich einige Anregungen geben, wie Sie diese leistungsstarke Funktion selbst nutzen können.


Überblick

Als Spezifikation ist IndexedDB derzeit eine Kandidatenempfehlung.

Kurz gesagt bietet IndexedDB eine Möglichkeit, große Datenmengen im Browser des Benutzers zu speichern. Jede Anwendung, die viele Daten über das Kabel senden muss, könnte erheblich davon profitieren, dass diese Daten stattdessen auf dem Client gespeichert werden können. Natürlich ist Lagerung nur ein Teil der Gleichung. IndexedDB bietet auch eine leistungsstarke, indizierte Such-API, um die benötigten Daten abzurufen.

Sie fragen sich vielleicht, wie sich IndexedDB von anderen Speichermechanismen unterscheidet?

Cookies werden sehr gut unterstützt, haben jedoch rechtliche Auswirkungen und beschränkten Speicherplatz. Außerdem werden sie mit jeder Anforderung hin und zurück zum Server gesendet, wodurch die Vorteile des clientseitigen Speichers vollständig aufgehoben werden.

Lokaler Speicher wird auch sehr gut unterstützt, ist jedoch hinsichtlich der Gesamtmenge an Speicher, die Sie verwenden können, begrenzt. Local Storage bietet keine echte Such-API, da Daten nur über Schlüsselwerte abgerufen werden. Lokaler Speicher eignet sich hervorragend für "bestimmte" Dinge, die Sie beispielsweise speichern möchten, während IndexedDB besser für Ad-hoc-Daten geeignet ist (ähnlich wie bei einer Datenbank)..

Bevor wir jedoch weiter gehen, sprechen wir ehrlich über den Stand von IndexedDB in Bezug auf die Browserunterstützung. Als Spezifikation ist IndexedDB derzeit eine Kandidatenempfehlung. An diesem Punkt sind die Leute hinter der Spezifikation zufrieden damit, suchen aber jetzt nach Feedback von der Entwicklergemeinde. Die Spezifikation kann sich zwischen jetzt und der W3C-Empfehlung in der Endphase ändern. Im Allgemeinen arbeiten Browser, die IndexedDB unterstützen, alle auf ziemlich konsistente Weise. Entwickler sollten jedoch darauf vorbereitet sein, mit Präfixen umzugehen und zukünftige Updates zu beachten.

Bei den Browsern, die IndexedDB unterstützen, besteht ein gewisses Dilemma. Der Support ist für den Desktop ziemlich gut, für das Handy praktisch nicht vorhanden. Mal sehen was der ist Ausgezeichnet Website CanIUse.com sagt:


Chrome für Android unterstützt diese Funktion zwar nicht, aber derzeit verwenden nur wenige Benutzer diesen Browser auf Android-Geräten. Bedeutet der Mangel an mobiler Unterstützung, dass Sie ihn nicht verwenden sollten? Natürlich nicht! Hoffentlich kennen alle unsere Leser das Konzept der progressiven Verbesserung. Funktionen wie IndexedDB können Ihrer Anwendung so hinzugefügt werden, dass nicht unterstützte Browser nicht beschädigt werden. Sie können Wrapper-Bibliotheken verwenden, um auf Mobile auf WebSQL zu wechseln, oder einfach das lokale Speichern von Daten auf Ihren mobilen Clients zu überspringen. Ich persönlich glaube, dass die Möglichkeit, große Datenblöcke auf dem Client zu cachen, wichtig genug ist, um sie jetzt auch ohne mobile Unterstützung nutzen zu können.


Lass uns anfangen

Wir haben die Spezifikationen und den Support behandelt, nun schauen wir uns die Funktion an. Das allererste, was wir tun sollten, ist nach IndexedDB-Unterstützung zu suchen. Es gibt zwar Tools, die generische Möglichkeiten bieten, nach Browserfunktionen zu suchen. Wir können dies jedoch wesentlich vereinfachen, da wir nur nach einer bestimmten Sache suchen.

document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" im Fenster) console.log ("JA !!! Ich kann es !!! WOOT !!!"); else console.log ("Ich habe ein trauriges.");, Falsch);

Das obige Code-Snippet (verfügbar in test1.html Wenn Sie die ZIP-Datei herunterladen, die diesem Artikel angehängt ist, wird die DOMContentLoaded Ereignis, das auf das Laden der Seite wartet. (Ok, das ist offensichtlich, aber ich weiß, dass es Leuten, die nur mit jQuery gearbeitet haben, vielleicht nicht vertraut ist.) Dann sehe ich einfach, ob indexedDB in der vorhanden ist Fenster Objekt und wenn ja, sind wir gut zu gehen. Das ist das einfachste Beispiel, aber normalerweise möchten wir dies wahrscheinlich speichern, sodass wir später wissen, ob wir die Funktion verwenden können. Hier ist ein etwas fortgeschritteneres Beispiel (test2.html).

var idbSupported = false; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" im Fenster) idbSupported = true;, false);

Ich habe nur eine globale Variable erstellt, idbSupported, Dies kann als Flag verwendet werden, um festzustellen, ob der aktuelle Browser IndexedDB verwenden kann.


Datenbank öffnen

IndexedDB verwendet, wie Sie sich vorstellen können, Datenbanken. Das ist keine SQL Server-Implementierung. Diese Datenbank ist lokal für den Browser und nur für den Benutzer verfügbar. IndexedDB-Datenbanken folgen den gleichen Regeln wie Cookies und lokaler Speicher. Eine Datenbank ist für die Domäne eindeutig, aus der sie geladen wurde. Eine bei foo.com erstellte Datenbank mit dem Namen "Foo" steht beispielsweise nicht in Konflikt mit einer gleichnamigen Datenbank auf goo.com. Es wird nicht nur kein Konflikt entstehen, es ist auch nicht für andere Domains verfügbar. Sie können Daten für Ihre Website speichern und wissen, dass eine andere Website nicht darauf zugreifen kann.

Das Öffnen einer Datenbank erfolgt über den Befehl "Öffnen". In der Grundnutzung geben Sie einen Namen und eine Version an. Die Version ist sehr wichtig aus Gründen, die ich später näher erläutern werde. Hier ist ein einfaches Beispiel:

var openRequest = indexedDB.open ("test", 1);

Das Öffnen einer Datenbank ist ein asynchroner Vorgang. Um mit dem Ergebnis dieser Operation fertig zu werden, müssen Sie einige Ereignis-Listener hinzufügen. Es gibt vier verschiedene Arten von Ereignissen, die ausgelöst werden können:

  • Erfolg
  • Error
  • aufgerüstet
  • verstopft

Sie können wahrscheinlich erraten, was Erfolg und Fehler bedeuten. Das aufgerüstete Ereignis wird sowohl beim ersten Öffnen der Datenbank als auch beim Ändern der Version verwendet. Blockiert geschieht normalerweise nicht, kann aber ausgelöst werden, wenn zuvor keine Verbindung geschlossen wurde.

Normalerweise sollte Folgendes passieren: Beim ersten Treffer an Ihrer Site wird das aktualisierte Ereignis ausgelöst. Danach - nur der Erfolgsbehandler. Schauen wir uns ein einfaches Beispiel an (test3.html).

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" im Fenster) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test", 1); openRequest.onupgradeneed = Funktion (e) console.log ("Aktualisieren ..."); openRequest.onsuccess = Funktion (e) Console.log ("Erfolg!"); db = e.target.result; openRequest.onerror = Funktion (e ) console.log ("Error"); console.dir (e);, false);

Wir prüfen noch einmal, ob IndexedDB tatsächlich unterstützt wird, und wenn ja, öffnen wir eine Datenbank. Wir haben hier drei Ereignisse behandelt - das erforderliche Upgrade-Ereignis, das Erfolgsereignis und das Fehlerereignis. Konzentrieren Sie sich jetzt auf die Erfolgsveranstaltung. Die Veranstaltung wird einem Handler über übergeben target.result. Wir haben das in eine globale Variable kopiert db. Dies wird später verwendet, um tatsächlich Daten hinzuzufügen. Wenn Sie dies in Ihrem Browser ausführen (in einem, der natürlich IndexedDB unterstützt!), Sollten Sie die Upgrade- und Erfolgsmeldung beim ersten Ausführen des Skripts in Ihrer Konsole sehen. Beim zweiten Ausführen des Skripts sollten Sie nur die Erfolgsmeldung sehen.


Objektspeicher

Bisher haben wir die IndexedDB-Unterstützung geprüft, bestätigt und eine Verbindung zu einer Datenbank hergestellt. Jetzt brauchen wir einen Ort zum Speichern von Daten. IndexedDB hat ein Konzept von "Objektspeichern". Sie können sich dies als eine typische Datenbanktabelle vorstellen. (Es ist viel lockerer als eine typische Datenbanktabelle, aber machen Sie sich jetzt keine Sorgen.) Objektspeicher haben (offensichtlich) Daten, aber auch einen Schlüsselpfad und einen optionalen Satz von Indizes. Tastaturpfade sind im Wesentlichen eindeutige Bezeichner für Ihre Daten und in verschiedenen Formaten verfügbar. Indizes werden später behandelt, wenn wir über das Abrufen von Daten sprechen.

Nun zu etwas Entscheidendem. Erinnern Sie sich an die bereits erwähnte verbesserte Veranstaltung? Sie können Objektspeicher nur während eines aktualisierten Ereignisses erstellen. Jetzt standardmäßig - dies wird automatisch ausgeführt, wenn ein Benutzer zum ersten Mal Ihre Site besucht. Sie können dies zum Erstellen Ihrer Objektspeicher verwenden. Die entscheidende Sache, die Sie sich merken sollten, ist, wenn Sie es jemals brauchen ändern In Ihren Objektspeichern müssen Sie die Version aktualisieren (in diesem offenen Ereignis) und Code schreiben, um Ihre Änderungen zu bearbeiten. Schauen wir uns ein einfaches Beispiel in Aktion an.

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" im Fenster) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test_v2", 1); openRequest.onupgradeneed = Funktion (e) console.log ("wird bei Aktualisierung ausgeführt"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS"); openRequest .onsuccess = function (e) console.log ("Erfolg!"); db = e.target.result; openRequest.onerror = function (e) console.log ("Error"); console.dir (e ;, falsch);

Dieses Beispiel (test4.html) baut auf den vorherigen Einträgen auf, so dass ich mich auf das Neue konzentrieren werde. Innerhalb des aktualisierten Ereignisses habe ich die an ihn übergebene Datenbankvariable verwendet (thisDB). Eine der Eigenschaften dieser Variablen ist eine Liste der vorhandenen Objektspeicher objectStoreNames. Für Neugierige ist dies kein einfaches Array, sondern eine "DOMStringList". Frag mich nicht - aber los gehts. Wir können die verwenden enthält Methode, um zu sehen, ob unser Objektspeicher existiert, und erstellen Sie ihn, falls nicht. Dies ist eine der wenigen synchronen Funktionen in IndexedDB, sodass wir nicht auf das Ergebnis achten müssen.

Zusammenfassend lässt sich sagen, dass dies passieren würde, wenn ein Benutzer Ihre Website besucht. Das erste Mal, dass sie hier sind, wird das verbesserte Ereignis ausgelöst. Der Code prüft, ob ein Objektspeicher "firstOS" vorhanden ist. Es wird nicht. Deshalb wird es geschaffen. Dann läuft der Erfolgsmanager. Wenn Sie die Website zum zweiten Mal besuchen, ist die Versionsnummer identisch, sodass das aktualisierte Ereignis der Fall ist nicht gefeuert.

Nun stellen Sie sich vor, Sie wollten einen zweiten Objektspeicher hinzufügen. Alles, was Sie tun müssen, ist die Versionsnummer zu erhöhen und den inhalt / createObjectStore-Codeblock zu kopieren, den Sie oben sehen. Das Coole daran ist, dass Ihr überarbeiteter Code sowohl Personen unterstützt, die auf der Website ganz neu sind, als auch diejenigen, die bereits den ersten Objektspeicher hatten. Hier ist ein Beispiel dafür (test5.html):

var openRequest = indexedDB.open ("test_v2", 2); openRequest.onupgradeneeded = function (e) console.log ("läuft auf Upgradeneeded"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS");  if (! thisDB.objectStoreNames.contains ("secondOS")) thisDB.createObjectStore ("secondOS"); 

Daten hinzufügen

Sobald Sie Ihre Objektspeicher eingerichtet haben, können Sie mit dem Hinzufügen von Daten beginnen. Dies ist - vielleicht - einer der coolsten Aspekte von IndexedDB. Im Gegensatz zu herkömmlichen tabellenbasierten Datenbanken können Sie mit IndexedDB ein Objekt so speichern, wie es ist. Das bedeutet, Sie können ein generisches JavaScript-Objekt verwenden und es einfach speichern. Erledigt. Offensichtlich gibt es hier einige Einschränkungen, aber zum größten Teil ist es das.

Um mit Daten arbeiten zu können, müssen Sie eine Transaktion verwenden. Transaktionen erfordern zwei Argumente. Die erste ist ein Array von Tabellen, mit denen Sie arbeiten. Meist wird dies eine Tabelle sein. Das zweite Argument ist die Art der Transaktion. Es gibt zwei Arten von Transaktionen: Readonly und Readwrite. Das Hinzufügen von Daten ist eine Leseoperation. Beginnen wir mit dem Erstellen der Transaktion:

// Angenommen, db ist eine zuvor geöffnete Datenbankvariable var transaction = db.transaction (["people"], "readwrite");

Beachten Sie, dass der Objektspeicher "Personen" nur ein Beispiel ist, das wir im obigen Beispiel erstellt haben. Unsere nächste vollständige Demo wird davon Gebrauch machen. Nachdem Sie die Transaktion erhalten haben, fragen Sie sie nach dem Objektspeicher, mit dem Sie gesagt haben, dass Sie damit arbeiten würden:

var store = transaction.objectStore ("Personen");

Nun, da Sie den Speicher haben, können Sie Daten hinzufügen. Dies geschieht über die - Wartezeit - hinzufügen Methode.

// Eine Person definieren var person = Name: Name, E-Mail: E-Mail, erstellt: neues Datum () // Füge das Hinzufügen hinzu var request = store.add (person, 1);

Denken Sie daran, dass wir gesagt haben, dass Sie alle Daten speichern können, die Sie möchten (zum größten Teil). Mein persönliches Objekt ist also völlig willkürlich. Ich hätte firstName und lastName anstelle von nur name verwenden können. Ich hätte ein Geschlechtseigentum verwenden können. Du hast die Idee. Das zweite Argument ist der Schlüssel, mit dem die Daten eindeutig identifiziert werden. In diesem Fall haben wir es hart auf 1 programmiert, was ziemlich schnell ein Problem verursachen wird. Das ist in Ordnung - wir lernen, wie man es korrigiert.

Die Add-Operation ist ascynchronous. Fügen Sie also zwei Event-Handler für das Ergebnis hinzu.

request.onerror = Funktion (e) console.log ("Fehler", e.target.error.name); // Irgendeine Art Fehlerhandler request.onsuccess = function (e) console.log ("Woot! Did it"); 

Wir haben eine Onerror Handler für Fehler und Ein Erfolg für gute änderungen. Ziemlich offensichtlich, aber sehen wir uns ein vollständiges Beispiel an. Sie finden dies in der Datei test6.html.

>
      

Das obige Beispiel enthält ein kleines Formular mit einer Schaltfläche zum Auslösen eines Ereignisses zum Speichern der Daten in IndexedDB. Führen Sie dies in Ihrem Browser aus, fügen Sie den Formularfeldern etwas hinzu und klicken Sie auf Hinzufügen. Wenn Sie die Browser-Tools Ihres Browsers geöffnet haben, sollten Sie so etwas sehen.


Dies ist eine gute Gelegenheit, um darauf hinzuweisen, dass Chrome einen hervorragenden Viewer für IndexedDB-Daten bietet. Wenn Sie auf die Registerkarte Ressourcen klicken, erweitern Sie den Abschnitt IndexedDB, um die von dieser Demo erstellte Datenbank sowie das soeben eingegebene Objekt anzuzeigen.


Fahren Sie einfach fort und klicken Sie erneut auf die Schaltfläche Daten hinzufügen. Sie sollten einen Fehler in der Konsole sehen:


Die Fehlermeldung sollte ein Hinweis sein. ConstraintError bedeutet, dass wir gerade versucht haben, Daten mit demselben Schlüssel wie einem bereits vorhandenen hinzuzufügen. Wenn Sie sich erinnern, haben wir diesen Schlüssel hart codiert und wir wusste das würde ein Problem werden. Es ist Zeit, Schlüssel zu sprechen.


Schlüssel

Schlüssel sind die Version der Primärschlüssel von IndexedDB. Traditionelle Datenbanken können Tabellen ohne Schlüssel enthalten, aber jeder Objektspeicher muss einen Schlüssel haben. IndexedDB ermöglicht verschiedene Schlüsselarten.

Die erste Möglichkeit ist, es einfach selbst anzugeben, wie wir es oben gemacht haben. Wir könnten Logik verwenden, um eindeutige Schlüssel zu generieren.

Die zweite Option ist ein Schlüsselpfad, bei dem der Schlüssel auf einer Eigenschaft der Daten selbst basiert. Betrachten Sie unsere Mitarbeiter als Beispiel - wir könnten eine E-Mail-Adresse als Schlüssel verwenden.

Ihre dritte Option, und meiner Meinung nach die einfachste, ist die Verwendung eines Schlüsselgenerators. Dies funktioniert ähnlich wie ein Primärschlüssel mit automatischer Nummerierung und ist die einfachste Methode, Schlüssel anzugeben.

Schlüssel werden beim Erstellen von Objektspeichern definiert. Hier sind zwei Beispiele - eines mit einem Schlüsselpfad und eines mit einem Generator.

thisDb.createObjectStore ("test", keyPath: "email"); thisDb.createObjectStore ("test2", autoIncrement: true);

Wir können unsere vorherige Demo modifizieren, indem Sie einen Objektspeicher mit einem autoIncrement-Schlüssel erstellen:

thisDB.createObjectStore ("people", autoIncrement: true);

Schließlich können wir den zuvor verwendeten Aufruf "Hinzufügen" annehmen und den fest codierten Schlüssel entfernen:

var request = store.add (person);

Das ist es! Jetzt können Sie den ganzen Tag Daten hinzufügen. Sie finden diese Version in test7.html.


Daten lesen

Wechseln wir nun zum Lesen einzelner Daten (später lesen wir das Lesen größerer Datensätze). Dies wird wiederum in einer Transaktion durchgeführt und ist asynchron. Hier ist ein einfaches Beispiel:

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); // x ist ein Wert var ob = objectStore.get (x); ob.onsuccess = Funktion (e) 

Beachten Sie, dass die Transaktion schreibgeschützt ist. Der API-Aufruf ist nur ein einfacher Get-Aufruf, bei dem der Schlüssel übergeben wird. Wenn Sie denken, dass IndexedDB ein wenig ausführlich ist, können Sie auch viele dieser Aufrufe verketten. Hier ist der exakt gleiche Code viel enger geschrieben:

db.transaction (["test"], "readonly"). objectStore ("test"). get (X) .onsuccess = Funktion (e) 

Persönlich finde ich IndexedDB immer noch etwas komplex, deshalb bevorzuge ich die "ausgeknackte" Herangehensweise, damit ich den Überblick behalten kann.

Das Ergebnis des onsuccess-Handlers von get ist das Objekt, das Sie zuvor gespeichert haben. Sobald Sie diesen Gegenstand haben, können Sie tun, was Sie wollen. In unserer nächsten Demo (test8.html) Wir haben ein einfaches Formularfeld hinzugefügt, mit dem Sie einen Schlüssel eingeben und das Ergebnis drucken können. Hier ist ein Beispiel:


Der Handler für die Schaltfläche Daten abrufen befindet sich unten:

function getPerson (e) var key = document.querySelector ("# key"). value; if (Schlüssel === "" || isNaN (Schlüssel)) return; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("Personen"); var request = store.get (Nummer (Schlüssel)); request.onsuccess = Funktion (e) var result = e.target.result; console.dir (Ergebnis); if (Ergebnis) var s = "

Taste "+ Taste +"

"; für (var Feld im Ergebnis) s + = Feld +" = "+ Ergebnis [Feld] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Keine Übereinstimmung

";

Dies sollte zum größten Teil selbsterklärend sein. Rufen Sie den Wert aus dem Feld ab und führen Sie einen Get-Aufruf für den Objektspeicher aus, der von einer Transaktion abgerufen wird. Beachten Sie, dass der Anzeigecode einfach angezeigt wird alles die Felder und entleert sie. In einer realen Anwendung würden Sie (hoffentlich) wissen, was Ihre Daten enthalten, und mit bestimmten Feldern arbeiten.


Weitere Daten lesen

So erhalten Sie eine einzige Datenmenge. Wie wäre es mit einer Menge von Dateien? IndexedDB unterstützt das, was als Cursor bezeichnet wird. Mit einem Cursor können Sie Daten iterieren. Sie können Cursor mit einem optionalen Bereich (einem Basisfilter) und einer Richtung erstellen.

Als Beispiel öffnet der folgende Codeblock einen Cursor, um alle Daten aus einem Objektspeicher abzurufen. Wie alles andere, was wir mit Daten gemacht haben, ist dies asynchron und in einer Transaktion.

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); var Cursor = objectStore.openCursor (); cursor.onsuccess = Funktion (e) var res = e.target.result; if (res) console.log ("Key", res.key); console.dir ("Data", Wiedergabewert); res.continue (); 

Dem Erfolgshandler wird ein Ergebnisobjekt übergeben (die Variable res oben). Sie enthält den Schlüssel, das Objekt für die Daten (im Wertschlüssel oben) und eine continue-Methode, mit der das nächste Datenelement durchlaufen wird.

In der folgenden Funktion haben wir einen Cursor verwendet, um alle Objektspeicherdaten zu durchlaufen. Da wir mit "Person" -Daten arbeiten, haben wir diesen getPeople genannt:

Funktion getPeople (e) var s = ""; db.transaction (["people"], "readonly"). objectStore ("people"). openCursor (). onsuccess = Funktion (e) var Cursor = e.target.result; if (Cursor) s + = "

Taste "+ Cursor.Taste +"

"; für (var Feld in Cursor.Wert) s + = Feld +" = "+ Cursor.Wert [Feld] +"
"; s + ="

"; Cursor.continue (); document.querySelector (" # status2 "). innerHTML = s;

Sie können eine vollständige Demo davon in Ihrem Download als Datei sehen test9.html. Es verfügt wie in den vorherigen Beispielen über eine Personen hinzufügen-Logik. Legen Sie einfach ein paar Personen an und drücken Sie die Taste, um alle Daten anzuzeigen.


Jetzt wissen Sie, wie Sie eine einzelne Dateneinheit erhalten und wie alle Daten abgerufen werden. Kommen wir nun zu unserem letzten Thema - dem Arbeiten mit Indizes.


Sie nennen dies IndexedDB, richtig?

Wir haben im gesamten Artikel über IndexedDB gesprochen, aber bisher noch keine - gut - Indizes erstellt. Indizes sind ein entscheidender Bestandteil von IndexedDB-Objektspeichern. Sie bieten eine Möglichkeit, Daten basierend auf ihrem Wert abzurufen und anzugeben, ob ein Wert innerhalb eines Geschäfts eindeutig sein soll. Später zeigen wir Ihnen, wie Sie mithilfe von Indizes eine Reihe von Daten abrufen können.

Erstens - wie erstellen Sie einen Index? Sie müssen wie alle anderen strukturellen Elemente in einem Aktualisierungsereignis ausgeführt werden, im Wesentlichen zur gleichen Zeit, zu der Sie Ihren Objektspeicher erstellen. Hier ist ein Beispiel:

var objectStore = thisDb.createObjectStore ("people", autoIncrement: true); // Das erste Argument ist der Name des Indexes, das Zweite ist der Pfad (col). objectStore.createIndex ("name", "name", unique: false); objectStore.createIndex ("email", "email", unique: true);

In der ersten Zeile erstellen wir den Laden. Wir nehmen dieses Ergebnis (ein objectStore-Objekt) und führen das aus createIndex Methode. Das erste Argument ist der Name für den Index und das zweite ist die Eigenschaft, die indiziert werden soll. In den meisten Fällen denke ich, dass Sie für beide denselben Namen verwenden werden. Das letzte Argument ist eine Reihe von Optionen. Im Moment verwenden wir nur einen einzigen. Der erste Index für name ist nicht eindeutig. Die zweite für E-Mail ist. Wenn wir Daten speichern, überprüft IndexedDB diese Indizes und stellt sicher, dass die E-Mail-Eigenschaft eindeutig ist. Es wird auch einige Datenverarbeitung im Backend durchführen, um sicherzustellen, dass Daten über diese Indizes abgerufen werden können.

Wie funktioniert das? Wenn Sie einen Objektspeicher über eine Transaktion abrufen, können Sie einen Index von diesem Speicher anfordern. Verwenden Sie den obigen Code, hier ein Beispiel dafür:

var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("Personen"); var index = store.index ("name"); // Name ist ein Wert var var = index.get (name);

Zuerst erhalten wir die Transaktion, dann den Store und dann den Index. Wie wir bereits gesagt haben, können Sie die ersten drei Zeilen verketten, um sie etwas kompakter zu gestalten, wenn Sie möchten.

Sobald Sie einen Index haben, können Sie eine erhalten rufen Sie es an, um Daten nach Namen abzurufen. Wir könnten auch etwas Ähnliches für E-Mails tun. Das Ergebnis dieses Aufrufs ist ein weiteres asynchrones Objekt, an das Sie einen onsuccess-Handler binden können. Hier ist ein Beispiel für diesen Handler in der Datei test10.html:

request.onsuccess = Funktion (e) var result = e.target.result; if (Ergebnis) var s = "

Name "+ Name +"

"; für (var Feld im Ergebnis) s + = Feld +" = "+ Ergebnis [Feld] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Keine Übereinstimmung

";

Beachten Sie, dass ein Index erhalten Aufruf kann mehrere Objekte zurückgeben. Da unser Name nicht eindeutig ist, sollten Sie den Code wahrscheinlich ändern, um dies zu handhaben. Dies ist jedoch nicht erforderlich.

Lassen Sie uns jetzt eine Stufe höher schlagen. Sie haben gesehen, wie Sie die get-API für den Index verwenden, um einen auf dieser Eigenschaft basierenden Wert zu erhalten. Was ist, wenn Sie eine breitere Datenmenge erhalten möchten? Der letzte Begriff, den wir heute lernen werden, sind Ranges. Bereiche sind eine Möglichkeit, eine Teilmenge eines Index auszuwählen. Wenn Sie beispielsweise einen Index für eine Namenseigenschaft haben, können wir einen Bereich verwenden, um Namen zu finden, die mit A bis zu Namen beginnen, die mit C beginnen. Sie können "alles unter einem Marker", "alles über einem Marker" und "etwas zwischen einem unteren und einem höheren Marker" sein. Nur um die Dinge interessant zu machen, können Sortimente inklusiv oder exklusiv sein. Im Grunde bedeutet dies für einen Bereich, der von A-C geht, wir können angeben, ob A und C in den Bereich aufgenommen werden sollen oder nur die Werte zwischen ihnen. Schließlich können Sie auch aufsteigende und absteigende Bereiche anfordern.

Bereiche werden mit einem Toplevel-Objekt namens IDBKeyRange erstellt. Es gibt drei Methoden von Interesse: lowerBound, obere Grenze, und gebunden. lowerBound wird verwendet, um einen Bereich zu erstellen, der bei einem niedrigeren Wert beginnt und alle Daten "darüber" zurückgibt. obere Grenze ist das Gegenteil. Und schlussendlich - gebunden wird verwendet, um einen Datensatz mit einer unteren und oberen Grenze zu unterstützen. Schauen wir uns einige Beispiele an:

// Werte über 39 var oldRange = IDBKeyRange.lowerBound (39); // Werte 40a dn over var oldRange2 = IDBKeyRange.lowerBound (40, true); // 39 und kleiner… var youngRange = IDBKeyRange.upperBound (40); // 39 und kleiner… var youngRange2 = IDBKeyRange.upperBound (39, true); // nicht jung oder alt ... Sie können auch inklusive / exklusive var angeben. okRange = IDBKeyRange.bound (20,40)

Sobald Sie einen Bereich haben, können Sie ihn an die openCursor-Methode eines Index übergeben. Dies gibt Ihnen einen Iterator, um die Werte zu durchlaufen, die diesem Bereich entsprechen. Praktisch ist dies nicht wirklich eine Suche an sich. Sie können dies verwenden, um Inhalte basierend auf dem Anfang einer Zeichenfolge zu durchsuchen, nicht jedoch in der Mitte oder am Ende. Schauen wir uns ein vollständiges Beispiel an. Zuerst erstellen wir ein einfaches Formular, um Personen zu suchen:

Beginnen mit: 
Endet mit:

Wir werden Suchvorgänge zulassen, die aus einem der drei Typen von Bereichen bestehen (wiederum einen Wert und höher, einen Höchstwert oder die Werte innerhalb von zwei Eingaben). Schauen wir uns nun den Event-Handler für dieses Formular an.

Funktion getPeople (e) var name = document.querySelector ("# nameSearch"). value; var endname = document.querySelector ("# nameSearchEnd"). value; if (name == "" && endname == "") return; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("Personen"); var index = store.index ("name"); // Setze den Bereich abhängig von dem Typ, den wir machen var Bereich; if (name! = "" && endname! = "") range = IDBKeyRange.bound (name, endname);  else if (name == "") range = IDBKeyRange.upperBound (endname);  else range = IDBKeyRange.lowerBound (name);  var s = ""; index.openCursor (range) .onsuccess = Funktion (e) var Cursor = e.target.result; if (Cursor) s + = "

Taste "+ Cursor.Taste +"

"; für (var Feld in Cursor.Wert) s + = Feld +" = "+ Cursor.Wert [Feld] +"
"; s + ="

"; Cursor.continue (); document.querySelector (" # status "). innerHTML = s;

Von oben nach unten - wir fangen mit den zwei Formularfeldern an. Als Nächstes erstellen wir eine Transaktion und erhalten daraus das Geschäft und den Index. Nun zum semi-komplexen Teil. Da wir drei verschiedene Arten von Bereichen haben, die wir unterstützen müssen, müssen wir ein wenig bedingte Logik anwenden, um herauszufinden, welche Bereiche wir benötigen. Welchen Bereich wir erstellen, hängt davon ab, welche Felder Sie ausfüllen. Was schön ist, wenn wir den Bereich erst einmal haben, übergeben wir ihn einfach an den Index und öffnen den Cursor. Das ist es! Sie finden dieses vollständige Beispiel in test11.html. Vergewissern Sie sich, dass Sie zuerst einige Werte eingeben, damit Sie Daten suchen können.


Was kommt als nächstes?

Ob Sie es glauben oder nicht - wir haben erst mit der Diskussion über IndexedDB begonnen. Im nächsten Artikel werden weitere Themen behandelt, darunter Aktualisierungen und Löschungen, Array-basierte Werte und einige allgemeine Tipps zum Arbeiten mit IndexedDB.