Google is committed to advancing racial equity for Black communities. See how.
Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

Cloud Firestore Web Codelab

Tore

In diesem Codelab erstellen Sie eine Web-App für Restaurantempfehlungen, die von Cloud Firestore unterstützt wird .

img5.png

Was du lernen wirst

  • Lesen und Schreiben von Daten aus einer Web-App in den Cloud Firestore
  • Hören Sie Änderungen in Cloud Firestore-Daten in Echtzeit ab
  • Verwenden Sie Firebase-Authentifizierungs- und Sicherheitsregeln, um Cloud Firestore-Daten zu sichern
  • Schreiben Sie komplexe Cloud Firestore-Abfragen

Was du brauchen wirst

Stellen Sie vor dem Starten dieses Codelabs sicher, dass Sie Folgendes installiert haben:

Erstellen Sie ein Firebase-Projekt

  1. Klicken Sie in der Firebase-Konsole auf Projekt hinzufügen und benennen Sie das Firebase-Projekt FriendlyEats .

Merken Sie sich die Projekt-ID für Ihr Firebase-Projekt.

  1. Klicken Sie auf Projekt erstellen .

Die Anwendung, die wir erstellen werden, verwendet einige im Web verfügbare Firebase-Dienste:

  • Firebase-Authentifizierung zur einfachen Identifizierung Ihrer Benutzer
  • Cloud Firestore zum Speichern strukturierter Daten in der Cloud und sofortige Benachrichtigung, wenn die Daten aktualisiert werden
  • Firebase-Hosting zum Hosten und Bereitstellen Ihrer statischen Assets

Für dieses spezielle Codelab haben wir Firebase Hosting bereits konfiguriert. Für Firebase Auth und Cloud Firestore führen wir Sie jedoch durch die Konfiguration und Aktivierung der Dienste mithilfe der Firebase-Konsole.

Anonyme Authentifizierung aktivieren

Obwohl die Authentifizierung nicht im Mittelpunkt dieses Codelabs steht, ist es wichtig, eine Form der Authentifizierung in unserer App zu haben. Wir verwenden die anonyme Anmeldung. Dies bedeutet, dass der Benutzer ohne Aufforderung stillschweigend angemeldet wird.

Sie müssen die anonyme Anmeldung aktivieren .

  1. Suchen Sie in der Firebase-Konsole den Abschnitt Entwickeln im linken Navigationsbereich.
  2. Klicken Sie auf Authentifizierung, klicken Sie auf den Anmelde-Verfahren Registerkarte (oder klicken Sie hier um direkt dorthin zu gehen).
  3. Aktivieren Sie den anonymen Anmeldeanbieter und klicken Sie auf Speichern .

img7.png

Auf diese Weise kann sich die Anwendung stillschweigend bei Ihren Benutzern anmelden, wenn diese auf die Webanwendung zugreifen. Weitere Informationen finden Sie in der Dokumentation zur anonymen Authentifizierung .

Cloud Firestore aktivieren

Die App verwendet Cloud Firestore, um Restaurantinformationen und Bewertungen zu speichern und zu empfangen.

Sie müssen den Cloud Firestore aktivieren. Klicken Sie im Abschnitt Entwickeln der Firebase-Konsole auf Firestore . Klicken Sie im Bereich Cloud Firestore auf Datenbank erstellen .

Der Zugriff auf Daten im Cloud Firestore wird durch Sicherheitsregeln gesteuert. Wir werden später in diesem Codelab mehr über Regeln sprechen, aber zuerst müssen wir einige Grundregeln für unsere Daten festlegen, um loszulegen. Fügen Sie auf der Registerkarte Regeln der Firebase-Konsole die folgenden Regeln hinzu und klicken Sie dann auf Veröffentlichen .

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

Die oben genannten Regeln beschränken den Datenzugriff auf angemeldete Benutzer, wodurch verhindert wird, dass nicht authentifizierte Benutzer lesen oder schreiben. Dies ist besser als das Zulassen des öffentlichen Zugriffs, aber noch lange nicht sicher. Wir werden diese Regeln später im Codelab verbessern.

Klonen Sie das GitHub-Repository über die Befehlszeile:

git clone https://github.com/firebase/friendlyeats-web

Der Beispielcode sollte in das Verzeichnis 📁 friendlyeats-web geklont worden sein. Stellen Sie sicher, dass Ihre Befehlszeile von nun an von diesem Verzeichnis aus ausgeführt wird:

cd friendlyeats-web

Importieren Sie die Starter-App

Öffnen oder importieren Sie mit Ihrer IDE (WebStorm, Atom, Sublime, Visual Studio Code ...) das Verzeichnis 📁 friendlyeats-web . Dieses Verzeichnis enthält den Startcode für das Codelab, der aus einer noch nicht funktionierenden Restaurantempfehlungs-App besteht. Wir werden es in diesem Codelab funktionsfähig machen, sodass Sie den Code in diesem Verzeichnis bald bearbeiten müssen.

Über die Firebase-Befehlszeilenschnittstelle (CLI) können Sie Ihre Webanwendung lokal bereitstellen und Ihre Webanwendung für Firebase Hosting bereitstellen.

  1. Installieren Sie die CLI, indem Sie den folgenden Befehl npm ausführen:
npm -g install firebase-tools
  1. Stellen Sie sicher, dass die CLI korrekt installiert wurde, indem Sie den folgenden Befehl ausführen:
firebase --version

Stellen Sie sicher, dass die Version der Firebase-CLI Version 7.4.0 oder höher ist.

  1. Autorisieren Sie die Firebase-CLI, indem Sie den folgenden Befehl ausführen:
firebase login

Wir haben die Web-App-Vorlage so eingerichtet, dass die Konfiguration Ihrer App für Firebase Hosting aus dem lokalen Verzeichnis und den Dateien Ihrer App abgerufen wird. Dazu müssen wir Ihre App jedoch Ihrem Firebase-Projekt zuordnen.

  1. Stellen Sie sicher, dass Ihre Befehlszeile auf das lokale Verzeichnis Ihrer App zugreift.
  2. Verknüpfen Sie Ihre App mit Ihrem Firebase-Projekt, indem Sie den folgenden Befehl ausführen:
firebase use --add
  1. Wenn Sie dazu aufgefordert werden, wählen Sie Ihre Projekt-ID aus und geben Sie Ihrem Firebase-Projekt einen Alias.

Ein Alias ​​ist nützlich, wenn Sie mehrere Umgebungen haben (Produktion, Staging usw.). Verwenden Sie für dieses Codelab jedoch nur den default .

  1. Befolgen Sie die restlichen Anweisungen in Ihrer Befehlszeile.

Wir sind bereit, mit der Arbeit an unserer App zu beginnen! Lassen Sie uns unsere App lokal ausführen!

  1. Führen Sie den folgenden Firebase-CLI-Befehl aus:
firebase emulators:start --only hosting
  1. Ihre Befehlszeile sollte die folgende Antwort anzeigen:
hosting: Local server: http://localhost:5000

Wir verwenden den Firebase Hosting- Emulator, um unsere App lokal bereitzustellen. Die Web-App sollte jetzt unter http: // localhost: 5000 verfügbar sein.

  1. Öffnen Sie Ihre App unter http: // localhost: 5000 .

Sie sollten Ihre Kopie von FriendlyEats sehen, die mit Ihrem Firebase-Projekt verbunden wurde.

Die App hat sich automatisch mit Ihrem Firebase-Projekt verbunden und Sie stillschweigend als anonymer Benutzer angemeldet.

img2.png

In diesem Abschnitt schreiben wir einige Daten in den Cloud Firestore, damit wir die Benutzeroberfläche der App füllen können. Dies kann manuell über die Firebase-Konsole erfolgen , wir werden dies jedoch in der App selbst tun, um ein grundlegendes Schreiben im Cloud Firestore zu demonstrieren.

Datenmodell

Firestore-Daten werden in Sammlungen, Dokumente, Felder und Untersammlungen aufgeteilt. Wir werden jedes Restaurant als Dokument in einer Sammlung der obersten Ebene speichern, die als restaurants .

img3.png

Später speichern wir jede Bewertung in einer Untersammlung, die als ratings in jedem Restaurant bezeichnet wird.

img4.png

Fügen Sie Restaurants zu Firestore hinzu

Das Hauptmodellobjekt in unserer App ist ein Restaurant. Lassen Sie uns schreiben einige Code, der ein Restaurant Dokument zum fügt restaurants Sammlung.

  1. Öffnen Sie in Ihren heruntergeladenen Dateien scripts/FriendlyEats.Data.js .
  2. Finden Sie die Funktion FriendlyEats.prototype.addRestaurant .
  3. Ersetzen Sie die gesamte Funktion durch den folgenden Code.

FriendlyEats.Data.js

FriendlyEats.prototype.addRestaurant = function(data) {
  var collection = firebase.firestore().collection('restaurants');
  return collection.add(data);
};

Der obige Code fügt der restaurants ein neues Dokument hinzu. Die Dokumentdaten stammen aus einem einfachen JavaScript-Objekt. Wir tun dies , indem man zuerst einen Verweis auf eine Wolke Firestor Sammlung bekommen restaurants dann add ‚ing die Daten.

Fügen wir Restaurants hinzu!

  1. Kehren Sie in Ihrem Browser zu Ihrer FriendlyEats-App zurück und aktualisieren Sie sie.
  2. Klicken Sie auf Mock-Daten hinzufügen .

Die App generiert automatisch einen zufälligen Satz von Restaurantobjekten und ruft dann Ihre Funktion addRestaurant . Sie werden die Daten jedoch noch nicht in Ihrer eigentlichen Web-App sehen, da das Abrufen der Daten noch implementiert werden muss (der nächste Abschnitt des Codelabs).

Wenn Sie jedoch in der Firebase-Konsole zur Registerkarte Cloud Firestore navigieren, sollten Sie jetzt neue Dokumente in der restaurants !

img6.png

Herzlichen Glückwunsch, Sie haben gerade Daten aus einer Web-App in den Cloud Firestore geschrieben!

Im nächsten Abschnitt erfahren Sie, wie Sie Daten aus dem Cloud Firestore abrufen und in Ihrer App anzeigen.

In diesem Abschnitt erfahren Sie, wie Sie Daten aus dem Cloud Firestore abrufen und in Ihrer App anzeigen. Die beiden wichtigsten Schritte sind das Erstellen einer Abfrage und das Hinzufügen eines Snapshot-Listeners. Dieser Listener wird über alle vorhandenen Daten benachrichtigt, die mit der Abfrage übereinstimmen, und erhält Aktualisierungen in Echtzeit.

Lassen Sie uns zunächst die Abfrage erstellen, die die standardmäßige, ungefilterte Liste der Restaurants liefert.

  1. Gehen Sie zurück zu den scripts/FriendlyEats.Data.js .
  2. Finden Sie die Funktion FriendlyEats.prototype.getAllRestaurants .
  3. Ersetzen Sie die gesamte Funktion durch den folgenden Code.

FriendlyEats.Data.js

FriendlyEats.prototype.getAllRestaurants = function(renderer) {
  var query = firebase.firestore()
      .collection('restaurants')
      .orderBy('avgRating', 'desc')
      .limit(50);

  this.getDocumentsInQuery(query, renderer);
};

Im obigen Code erstellen wir eine Abfrage, mit der bis zu 50 Restaurants aus der Sammlung der obersten Ebene mit dem Namen " restaurants abgerufen werden, die nach der Durchschnittsbewertung geordnet sind (derzeit alle Null). Nachdem wir diese Abfrage deklariert haben, übergeben wir sie an die Methode getDocumentsInQuery() , die für das Laden und Rendern der Daten verantwortlich ist.

Dazu fügen wir einen Snapshot-Listener hinzu.

  1. Gehen Sie zurück zu den scripts/FriendlyEats.Data.js .
  2. Suchen Sie die Funktion FriendlyEats.prototype.getDocumentsInQuery .
  3. Ersetzen Sie die gesamte Funktion durch den folgenden Code.

FriendlyEats.Data.js

FriendlyEats.prototype.getDocumentsInQuery = function(query, renderer) {
  query.onSnapshot(function(snapshot) {
    if (!snapshot.size) return renderer.empty(); // Display "There are no restaurants".

    snapshot.docChanges().forEach(function(change) {
      if (change.type === 'removed') {
        renderer.remove(change.doc);
      } else {
        renderer.display(change.doc);
      }
    });
  });
};

Im obigen Code löst query.onSnapshot seinen Rückruf jedes Mal aus, query.onSnapshot sich das Ergebnis der Abfrage ändert.

  • Beim ersten Mal wird der Rückruf mit der gesamten Ergebnismenge der Abfrage ausgelöst, dh mit der gesamten restaurants von Cloud Firestore. Anschließend werden alle einzelnen Dokumente an die Funktion renderer.display .
  • Wenn ein Dokument gelöscht wird, entspricht change.type removed . In diesem Fall rufen wir eine Funktion auf, mit der das Restaurant von der Benutzeroberfläche entfernt wird.

Nachdem wir beide Methoden implementiert haben, aktualisieren Sie die App und stellen Sie sicher, dass die Restaurants, die wir zuvor in der Firebase-Konsole gesehen haben, jetzt in der App sichtbar sind. Wenn Sie diesen Abschnitt erfolgreich abgeschlossen haben, liest und schreibt Ihre App jetzt Daten mit Cloud Firestore!

Wenn sich Ihre Liste der Restaurants ändert, wird dieser Listener automatisch aktualisiert. Gehen Sie zur Firebase-Konsole und löschen Sie ein Restaurant manuell oder ändern Sie seinen Namen. Die Änderungen werden sofort auf Ihrer Website angezeigt!

img5.png

Bisher haben wir gezeigt, wie Sie mit onSnapshot Updates in Echtzeit abrufen können. Das ist jedoch nicht immer das, was wir wollen. Manchmal ist es sinnvoller, die Daten nur einmal abzurufen.

Wir möchten eine Methode implementieren, die ausgelöst wird, wenn ein Benutzer in Ihrer App auf ein bestimmtes Restaurant klickt.

  1. Gehen Sie zurück zu Ihren scripts/FriendlyEats.Data.js .
  2. Finden Sie die Funktion FriendlyEats.prototype.getRestaurant .
  3. Ersetzen Sie die gesamte Funktion durch den folgenden Code.

FriendlyEats.Data.js

FriendlyEats.prototype.getRestaurant = function(id) {
  return firebase.firestore().collection('restaurants').doc(id).get();
};

Nachdem Sie diese Methode implementiert haben, können Sie Seiten für jedes Restaurant anzeigen. Klicken Sie einfach auf ein Restaurant in der Liste und Sie sollten die Detailseite des Restaurants sehen:

img1.png

Derzeit können Sie keine Bewertungen hinzufügen, da wir das Hinzufügen von Bewertungen später im Codelab noch implementieren müssen.

Derzeit zeigt unsere App eine Liste von Restaurants an, aber der Benutzer kann nicht nach seinen Bedürfnissen filtern. In diesem Abschnitt verwenden Sie die erweiterte Abfrage von Cloud Firestore, um die Filterung zu aktivieren.

Hier ist ein Beispiel für eine einfache Abfrage zum Abrufen aller Dim Sum Restaurants:

var filteredQuery = query.where('category', '==', 'Dim Sum')

Wie der Name schon sagt, lässt die where() -Methode unsere Abfrage nur Mitglieder der Sammlung herunterladen, deren Felder den von uns festgelegten Einschränkungen entsprechen. In diesem Fall werden nur Restaurants heruntergeladen, deren category Dim Sum .

In unserer App kann der Benutzer mehrere Filter verketten, um bestimmte Abfragen zu erstellen, z. B. "Pizza in San Francisco" oder "Meeresfrüchte in Los Angeles, sortiert nach Beliebtheit".

Wir erstellen eine Methode, die eine Abfrage erstellt, die unsere Restaurants anhand mehrerer von unseren Benutzern ausgewählter Kriterien filtert.

  1. Gehen Sie zurück zu Ihren scripts/FriendlyEats.Data.js .
  2. Suchen Sie die Funktion FriendlyEats.prototype.getFilteredRestaurants .
  3. Ersetzen Sie die gesamte Funktion durch den folgenden Code.

FriendlyEats.Data.js

FriendlyEats.prototype.getFilteredRestaurants = function(filters, renderer) {
  var query = firebase.firestore().collection('restaurants');

  if (filters.category !== 'Any') {
    query = query.where('category', '==', filters.category);
  }

  if (filters.city !== 'Any') {
    query = query.where('city', '==', filters.city);
  }

  if (filters.price !== 'Any') {
    query = query.where('price', '==', filters.price.length);
  }

  if (filters.sort === 'Rating') {
    query = query.orderBy('avgRating', 'desc');
  } else if (filters.sort === 'Reviews') {
    query = query.orderBy('numRatings', 'desc');
  }

  this.getDocumentsInQuery(query, renderer);
};

Der obige Code fügt mehrere where Filter und eine einzelne orderBy Klausel hinzu, um eine zusammengesetzte Abfrage basierend auf Benutzereingaben zu erstellen. Unsere Abfrage gibt jetzt nur Restaurants zurück, die den Anforderungen des Benutzers entsprechen.

Aktualisieren Sie Ihre FriendlyEats-App in Ihrem Browser und stellen Sie sicher, dass Sie nach Preis, Stadt und Kategorie filtern können. Während des Testens werden in der JavaScript-Konsole Ihres Browsers folgende Fehler angezeigt:

The query requires an index. You can create it here: https://console.firebase.google.com/project/.../database/firestore/indexes?create_index=...

Diese Fehler sind darauf zurückzuführen, dass der Cloud Firestore für die meisten zusammengesetzten Abfragen Indizes benötigt. Durch das Erfordernis von Indizes für Abfragen bleibt der Cloud Firestore schnell skaliert.

Durch Öffnen des Links aus der Fehlermeldung wird automatisch die Benutzeroberfläche für die Indexerstellung in der Firebase-Konsole mit den richtigen Parametern geöffnet. Im nächsten Abschnitt werden die für diese Anwendung erforderlichen Indizes geschrieben und bereitgestellt.

Wenn wir nicht jeden Pfad in unserer App erkunden und den einzelnen Links zur Indexerstellung folgen möchten, können wir mithilfe der Firebase-CLI problemlos viele Indizes gleichzeitig bereitstellen.

  1. Im heruntergeladenen lokalen Verzeichnis Ihrer App finden Sie eine Datei firestore.indexes.json .

Diese Datei beschreibt alle Indizes, die für alle möglichen Filterkombinationen benötigt werden.

firestore.indexes.json

{
 "indexes": [
   {
     "collectionGroup": "restaurants",
     "queryScope": "COLLECTION",
     "fields": [
       { "fieldPath": "city", "order": "ASCENDING" },
       { "fieldPath": "avgRating", "order": "DESCENDING" }
     ]
   },

   ...

 ]
}
  1. Stellen Sie diese Indizes mit dem folgenden Befehl bereit:
firebase deploy --only firestore:indexes

Nach einigen Minuten sind Ihre Indizes aktiv und die Fehlermeldungen verschwinden.

In diesem Abschnitt können Benutzer Bewertungen an Restaurants senden. Bisher waren alle unsere Schriften atomar und relativ einfach. Wenn einer von ihnen fehlerhaft ist, werden wir den Benutzer wahrscheinlich nur auffordern, ihn erneut zu versuchen, oder unsere App würde den Schreibvorgang automatisch wiederholen.

Unsere App wird viele Benutzer haben, die eine Bewertung für ein Restaurant hinzufügen möchten, daher müssen wir mehrere Lese- und Schreibvorgänge koordinieren. Zunächst wird die Überprüfung selbst muss eingereicht werden, dann ist die Bewertung des Restaurants count und average rating aktualisiert werden müssen. Wenn einer dieser Fehler auftritt, der andere jedoch nicht, befinden wir uns in einem inkonsistenten Zustand, in dem die Daten in einem Teil unserer Datenbank nicht mit den Daten in einem anderen übereinstimmen.

Glücklicherweise bietet Cloud Firestore Transaktionsfunktionen, mit denen wir mehrere Lese- und Schreibvorgänge in einem einzigen atomaren Vorgang ausführen können, um sicherzustellen, dass unsere Daten konsistent bleiben.

  1. Gehen Sie zurück zu Ihren scripts/FriendlyEats.Data.js .
  2. Suchen Sie die Funktion FriendlyEats.prototype.addRating .
  3. Ersetzen Sie die gesamte Funktion durch den folgenden Code.

FriendlyEats.Data.js

FriendlyEats.prototype.addRating = function(restaurantID, rating) {
  var collection = firebase.firestore().collection('restaurants');
  var document = collection.doc(restaurantID);
  var newRatingDocument = document.collection('ratings').doc();

  return firebase.firestore().runTransaction(function(transaction) {
    return transaction.get(document).then(function(doc) {
      var data = doc.data();

      var newAverage =
          (data.numRatings * data.avgRating + rating.rating) /
          (data.numRatings + 1);

      transaction.update(document, {
        numRatings: data.numRatings + 1,
        avgRating: newAverage
      });
      return transaction.set(newRatingDocument, rating);
    });
  });
};

Im obigen Block lösen wir eine Transaktion aus, um die numerischen Werte von avgRating und numRatings im Restaurantdokument zu aktualisieren. Gleichzeitig fügen wir die neue rating der ratings .

Zu Beginn dieses Codelabs haben wir die Sicherheitsregeln unserer App festgelegt, um die Datenbank vollständig für Lese- oder Schreibvorgänge zu öffnen. In einer realen Anwendung möchten wir viel detailliertere Regeln festlegen, um unerwünschten Datenzugriff oder unerwünschte Änderungen zu verhindern.

  1. Klicken Sie im Abschnitt Entwickeln der Firebase-Konsole auf Datenbank .
  2. Klicken Sie im Abschnitt Cloud Firestore auf die Registerkarte Regeln (oder klicken Sie hier , um direkt dorthin zu gelangen).
  3. Ersetzen Sie die Standardeinstellungen durch die folgenden Regeln und klicken Sie dann auf Veröffentlichen .

firestore.rules

rules_version = '2';
service cloud.firestore {

  // Determine if the value of the field "key" is the same
  // before and after the request.
  function unchanged(key) {
    return (key in resource.data) 
      && (key in request.resource.data) 
      && (resource.data[key] == request.resource.data[key]);
  }

  match /databases/{database}/documents {
    // Restaurants:
    //   - Authenticated user can read
    //   - Authenticated user can create/update (for demo purposes only)
    //   - Updates are allowed if no fields are added and name is unchanged
    //   - Deletes are not allowed (default)
    match /restaurants/{restaurantId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null;
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys()) 
                    && unchanged("name");
      
      // Ratings:
      //   - Authenticated user can read
      //   - Authenticated user can create if userId matches
      //   - Deletes and updates are not allowed (default)
      match /ratings/{ratingId} {
        allow read: if request.auth != null;
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;
      }
    }
  }
}

Diese Regeln beschränken den Zugriff, um sicherzustellen, dass Clients nur sichere Änderungen vornehmen. Zum Beispiel:

  • Aktualisierungen eines Restaurantdokuments können nur die Bewertungen ändern, nicht den Namen oder andere unveränderliche Daten.
  • Bewertungen können nur erstellt werden, wenn die Benutzer-ID mit dem angemeldeten Benutzer übereinstimmt, wodurch Spoofing verhindert wird.

Alternativ zur Verwendung der Firebase-Konsole können Sie die Firebase-CLI verwenden, um Regeln für Ihr Firebase-Projekt bereitzustellen. Die Datei firestore.rules in Ihrem Arbeitsverzeichnis enthält bereits die oben genannten Regeln. Um diese Regeln von Ihrem lokalen Dateisystem aus bereitzustellen (anstatt die Firebase-Konsole zu verwenden), führen Sie den folgenden Befehl aus:

firebase deploy --only firestore:rules

In diesem Codelab haben Sie gelernt, wie Sie mit Cloud Firestore grundlegende und erweiterte Lese- und Schreibvorgänge ausführen und den Datenzugriff mit Sicherheitsregeln sichern. Die vollständige Lösung finden Sie im Repository von quickstarts-js .

Weitere Informationen zum Cloud Firestore finden Sie in den folgenden Ressourcen: