Mit Firebase Data Connect (Web) entwickeln

1. Hinweis

FriendlyMovies App

In diesem Codelab integrieren Sie Firebase Data Connect in eine Cloud SQL-Datenbank, um eine Webanwendung für Filmbesprechungen zu erstellen. Die fertige App zeigt, wie Firebase Data Connect das Erstellen von SQL-basierten Anwendungen vereinfacht. Sie umfasst folgende Funktionen:

  • Authentifizierung:Implementieren Sie eine benutzerdefinierte Authentifizierung für die Abfragen und Mutationen Ihrer App, damit nur autorisierte Nutzer mit Ihren Daten interagieren können.
  • GraphQL-Schema:Erstellen und verwalten Sie Ihre Datenstrukturen mit einem flexiblen GraphQL-Schema, das auf die Anforderungen einer Webanwendung für Filmrezensionen zugeschnitten ist.
  • SQL-Abfragen und ‑Mutationen:Daten in Cloud SQL mithilfe von Abfragen und Mutationen abrufen, aktualisieren und verwalten, die auf GraphQL basieren.
  • Erweiterte Suche mit teilweiser Stringübereinstimmung:Mit Filtern und Suchoptionen können Sie Filme anhand von Feldern wie Titel, Beschreibung oder Tags finden.
  • (Optional) Vektorsuche integrieren:Fügen Sie eine Funktion für die Inhaltssuche hinzu, indem Sie die Vektorsuche von Firebase Data Connect verwenden. So können Sie eine umfassende Nutzererfahrung auf Grundlage von Eingaben und Einstellungen bieten.

Voraussetzungen

Sie benötigen grundlegende Kenntnisse in JavaScript.

Lerninhalte

  • Firebase Data Connect mit lokalen Emulatoren einrichten
  • Entwerfen Sie ein Datenschema mit Data Connect und GraphQL.
  • Verschiedene Abfragen und Mutationen für eine Filmbewertungs-App schreiben und testen.
  • Hier erfahren Sie, wie das SDK in der App von Firebase Data Connect generiert und verwendet wird.
  • Stellen Sie Ihr Schema bereit und verwalten Sie die Datenbank effizient.

Voraussetzungen

  • Git
  • Visual Studio Code
  • Installieren Sie Node.js mit nvm-windows (Windows) oder nvm (macOS/Linux).
  • Erstellen Sie ein Firebase-Projekt in der Firebase Console, falls noch nicht geschehen.
  • (Optional) Für die Vektorsuche: Führen Sie für Ihr Projekt ein Upgrade auf den Blaze-Tarif (Pay as you go) durch.

2. Entwicklungsumgebung einrichten

In dieser Phase des Codelabs wird beschrieben, wie Sie die Umgebung einrichten, um Ihre Filmbesprechungs-App mit Firebase Data Connect zu erstellen.

  1. Klonen Sie das Projekt-Repository und installieren Sie die erforderlichen Abhängigkeiten:
    git clone https://github.com/firebaseextended/codelab-dataconnect-web
    cd codelab-dataconnect-web
    cd ./app && npm i
    npm run dev
    
  2. Öffnen Sie nach dem Ausführen dieser Befehle http://localhost:5173 in Ihrem Browser, um die lokal ausgeführte Web-App zu sehen. Dies dient als Ihr Frontend für die Entwicklung der Filmbewertungs-App und die Interaktion mit ihren Funktionen.93f6648a2532c606.png
  3. Öffnen Sie den geklonten Ordner codelab-dataconnect-web mit Visual Studio Code. Hier definieren Sie Ihr Schema, schreiben Abfragen und testen die Funktionen der App.
  4. Wenn Sie Data Connect-Funktionen verwenden möchten, installieren Sie die Firebase Data Connect Visual Studio-Erweiterung.
    Alternativ können Sie die Erweiterung über den Visual Studio Code Marketplace installieren oder in VS Code danach suchen.b03ee38c9a81b648.png
  5. Öffnen Sie ein vorhandenes Firebase-Projekt in der Firebase Console oder erstellen Sie ein neues.
  6. Verbinden Sie Ihr Firebase-Projekt mit der VSCode-Erweiterung „Firebase Data Connect“. Gehen Sie in der Erweiterung so vor:
    1. Klicken Sie auf die Schaltfläche Anmelden.
    2. Klicken Sie auf Firebase-Projekt verknüpfen und wählen Sie Ihr Firebase-Projekt aus.
    4bb2fbf8f9fac29b.png
  7. Starten Sie die Firebase-Emulatoren mit der VS Code-Erweiterung „Firebase Data Connect“:
    Klicken Sie auf Start Emulators (Emulatoren starten) und bestätigen Sie dann, dass die Emulatoren im Terminal ausgeführt werden.6d3d95f4cb708db1.png

3. Starter-Codebasis prüfen

In diesem Abschnitt sehen Sie sich die wichtigsten Bereiche des Starter-Codes der App an. Auch wenn in der App einige Funktionen fehlen, ist es hilfreich, die Gesamtstruktur zu verstehen.

Ordner- und Dateistruktur

In den folgenden Unterabschnitten erhalten Sie einen Überblick über die Ordner- und Dateistruktur der App.

Verzeichnis dataconnect/

Enthält Firebase Data Connect-Konfigurationen, Connectors (die Abfragen und Mutationen definieren) und Schemadateien.

  • schema/schema.gql: Definiert das GraphQL-Schema
  • connector/queries.gql: In Ihrer App benötigte Abfragen
  • connector/mutations.gql: Erforderliche Mutationen in Ihrer App
  • connector/connector.yaml: Konfigurationsdatei für die SDK-Generierung

Verzeichnis app/src/

Enthält die Anwendungslogik und die Interaktion mit Firebase Data Connect.

  • firebase.ts: Konfiguration für die Verbindung zu einer Firebase-App in Ihrem Firebase-Projekt.
  • lib/dataconnect-sdk/: Enthält das generierte SDK. Sie können den Speicherort der SDK-Generierung in der Datei connector/connector.yaml bearbeiten. SDKs werden automatisch generiert, sobald Sie eine Abfrage oder Mutation definieren.

4. Schema für Filmbesprechungen definieren

In diesem Abschnitt definieren Sie die Struktur und die Beziehungen zwischen den wichtigsten Einheiten in der Filmanwendung in einem Schema. Entitäten wie Movie, User, Actor und Review werden Datenbanktabellen zugeordnet. Beziehungen werden mithilfe von Firebase Data Connect und GraphQL-Schemaanweisungen hergestellt. Sobald die Funktion implementiert ist, kann Ihre App alles verarbeiten – von der Suche nach Filmen mit Top-Bewertungen und dem Filtern nach Genre bis hin zur Möglichkeit für Nutzer, Rezensionen zu schreiben, Favoriten zu markieren, ähnliche Filme zu finden oder sich Filme auf Grundlage von Texteingaben über die Vektorsuche empfehlen zu lassen.

Wichtige Einheiten und Beziehungen

Der Typ Movie enthält wichtige Details wie Titel, Genre und Tags, die von der App für Suchanfragen und Filmprofile verwendet werden. Mit dem Typ User werden Nutzerinteraktionen wie Rezensionen und Favoriten erfasst. Reviews Nutzer mit Filmen verbinden, sodass in der App von Nutzern erstellte Bewertungen und Feedback angezeigt werden können.

Die Beziehungen zwischen Filmen, Schauspielern und Nutzern machen die App dynamischer. Die MovieActor-Verknüpfungstabelle hilft dabei, Besetzungsdetails und Filmografien von Schauspielern anzuzeigen. Mit dem Typ FavoriteMovie können Nutzer Filme als Favoriten markieren, damit in der App eine personalisierte Favoritenliste angezeigt und beliebte Filme hervorgehoben werden können.

Movie-Tabelle einrichten

Der Typ Movie definiert die Hauptstruktur für eine Filmentität, einschließlich Feldern wie title, genre, releaseYear und rating.

Kopieren Sie das Code-Snippet und fügen Sie es in Ihre dataconnect/schema/schema.gql-Datei ein:

type Movie
  @table {
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  imageUrl: String!
  releaseYear: Int
  genre: String
  rating: Float
  description: String
  tags: [String]
}

Zusammenfassung

  • id:Eine eindeutige UUID für jeden Film, die mit @default(expr: "uuidV4()") generiert wird.

MovieMetadata-Tabelle einrichten

Mit dem Typ MovieMetadata wird eine 1:1-Beziehung zum Typ Movie hergestellt. Sie enthält zusätzliche Daten wie den Regisseur des Films.

Kopieren Sie das Code-Snippet und fügen Sie es in Ihre dataconnect/schema/schema.gql-Datei ein:

type MovieMetadata
  @table {
  # @ref creates a field in the current table (MovieMetadata)
  # It is a reference that holds the primary key of the referenced type
  # In this case, @ref(fields: "movieId", references: "id") is implied
  movie: Movie! @ref
  # movieId: UUID <- this is created by the above @ref
  director: String
}

Zusammenfassung

  • Film! @ref: Verweist auf den Typ Movie und stellt eine Fremdschlüsselbeziehung her.

Actor-Tabelle einrichten

Kopieren Sie das Code-Snippet und fügen Sie es in Ihre dataconnect/schema/schema.gql-Datei ein:

type Actor @table {
  id: UUID!
  imageUrl: String!
  name: String! @col(name: "name", dataType: "varchar(30)")
}

Der Typ Actor stellt einen Schauspieler in der Filmdatenbank dar. Jeder Schauspieler kann in mehreren Filmen mitspielen, wodurch eine n:m-Beziehung entsteht.

MovieActor-Tabelle einrichten

Kopieren Sie das Code-Snippet und fügen Sie es in Ihre dataconnect/schema/schema.gql-Datei ein:

type MovieActor @table(key: ["movie", "actor"]) {
  # @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type
  # In this case, @ref(fields: "id") is implied
  movie: Movie!
  # movieId: UUID! <- this is created by the implied @ref, see: implicit.gql

  actor: Actor!
  # actorId: UUID! <- this is created by the implied  @ref, see: implicit.gql

  role: String! # "main" or "supporting"
}

Zusammenfassung

  • movie:Verweist auf den Typ „Movie“ und generiert implizit den Fremdschlüssel „movieId: UUID!“.
  • actor:Verweist auf den Typ „Actor“ und generiert implizit einen Fremdschlüssel „actorId: UUID!“.
  • role:Definiert die Rolle des Schauspielers im Film (z.B. „main“ oder „supporting“).

User-Tabelle einrichten

Der Typ User definiert eine Nutzerentität, die mit Filmen interagiert, indem sie Rezensionen schreibt oder Filme als Favoriten markiert.

Kopieren Sie das Code-Snippet und fügen Sie es in Ihre dataconnect/schema/schema.gql-Datei ein:

type User
  @table {
  id: String! @col
  username: String! @col(dataType: "varchar(50)")
  # The following are generated from the @ref in the Review table
  # reviews_on_user
  # movies_via_Review
}

FavoriteMovie-Tabelle einrichten

Der Typ FavoriteMovie ist eine Join-Tabelle, in der Viele-zu-viele-Beziehungen zwischen Nutzern und ihren Lieblingsfilmen verwaltet werden. In jeder Tabelle wird ein User mit einem Movie verknüpft.

Kopieren Sie das Code-Snippet und fügen Sie es in Ihre dataconnect/schema/schema.gql-Datei ein:

type FavoriteMovie
  @table(name: "FavoriteMovies", singular: "favorite_movie", plural: "favorite_movies", key: ["user", "movie"]) {
  # @ref is implicit
  user: User!
  movie: Movie!
}

Zusammenfassung

  • movie:Verweist auf den Typ „Movie“ und generiert implizit einen Fremdschlüssel movieId: UUID!.
  • user:Verweist auf den Nutzertyp und generiert implizit einen Fremdschlüssel userId: UUID!.

Review-Tabelle einrichten

Der Typ Review stellt die Rezensionsentität dar und verknüpft die Typen User und Movie in einer m:n-Beziehung (ein Nutzer kann viele Rezensionen hinterlassen und jeder Film kann viele Rezensionen haben).

Kopieren Sie das Code-Snippet und fügen Sie es in Ihre dataconnect/schema/schema.gql-Datei ein:

type Review @table(name: "Reviews", key: ["movie", "user"]) {
  id: UUID! @default(expr: "uuidV4()")
  user: User!
  movie: Movie!
  rating: Int
  reviewText: String
  reviewDate: Date! @default(expr: "request.time")
}

Zusammenfassung

  • user:Verweist auf den Nutzer, der die Rezension geschrieben hat.
  • movie:Verweist auf den Film, der rezensiert wird.
  • reviewDate:Wird automatisch auf den Zeitpunkt festgelegt, zu dem die Rezension mit @default(expr: "request.time") erstellt wird.

Automatisch generierte Felder und Standardwerte

Im Schema werden Ausdrücke wie @default(expr: "uuidV4()") verwendet, um automatisch eindeutige IDs und Zeitstempel zu generieren. Das Feld id in den Typen Movie und Review wird beispielsweise automatisch mit einer UUID gefüllt, wenn ein neuer Datensatz erstellt wird.

Nachdem das Schema definiert wurde, hat deine Filmapp eine solide Grundlage für ihre Datenstruktur und Beziehungen.

5. Die beliebtesten und neuesten Filme abrufen

FriendlyMovies App

In diesem Abschnitt fügen Sie Mock-Filmdaten in die lokalen Emulatoren ein und implementieren dann die Connectors (Abfragen) und den TypeScript-Code, um diese Connectors in der Webanwendung aufzurufen. Am Ende kann Ihre App die am besten bewerteten und neuesten Filme direkt aus der Datenbank abrufen und anzeigen.

Beispieldaten für Filme, Schauspieler und Rezensionen einfügen

  1. Öffnen Sie in VS Code dataconnect/moviedata_insert.gql. Prüfen Sie, ob die Emulatoren in der Firebase Data Connect-Erweiterung ausgeführt werden.
  2. Oben in der Datei sollte die Schaltfläche Lokal ausführen angezeigt werden. Klicken Sie darauf, um die Mock-Filmdaten in Ihre Datenbank einzufügen.
    e424f75e63bf2e10.png
  3. Prüfen Sie im Terminal Data Connect Execution, ob die Daten erfolgreich hinzugefügt wurden.
    e0943d7704fb84ea.png

Connector implementieren

  1. Öffnen Sie dataconnect/movie-connector/queries.gql. In den Kommentaren finden Sie eine einfache ListMovies-Abfrage:
    query ListMovies @auth(level: PUBLIC) {
      movies {
        id
        title
        imageUrl
        releaseYear
        genre
        rating
        tags
        description
      }
    }
    
    Mit dieser Abfrage werden alle Filme und ihre Details (z. B. id, title, releaseYear) abgerufen. Die Filme werden jedoch nicht sortiert.
  2. Ersetzen Sie die vorhandene ListMovies-Abfrage durch die folgende, um Sortier- und Begrenzungsoptionen hinzuzufügen:
    # List subset of fields for movies
    query ListMovies($orderByRating: OrderDirection, $orderByReleaseYear: OrderDirection, $limit: Int) @auth(level: PUBLIC) {
      movies(
        orderBy: [
          { rating: $orderByRating },
          { releaseYear: $orderByReleaseYear }
        ]
        limit: $limit
      ) {
        id
        title
        imageUrl
        releaseYear
        genre
        rating
        tags
        description
      }
    }
    
  3. Klicken Sie auf die Schaltfläche Lokal ausführen, um die Abfrage für Ihre lokale Datenbank auszuführen. Sie können die Abfragevariablen auch vor der Ausführung im Konfigurationsbereich eingeben.
    c4d947115bb11b16.png

Zusammenfassung

  • movies():GraphQL-Abfragefeld zum Abrufen von Filmdaten aus der Datenbank.
  • orderByRating:Parameter zum Sortieren von Filmen nach Bewertung (aufsteigend/absteigend).
  • orderByReleaseYear:Parameter zum Sortieren von Filmen nach Erscheinungsjahr (aufsteigend/absteigend).
  • limit:Beschränkt die Anzahl der zurückgegebenen Filme.

Anfragen in die Web-App einbinden

In diesem Teil des Codelabs verwenden Sie die im vorherigen Abschnitt definierten Abfragen in Ihrer Web-App. Die Firebase Data Connect-Emulatoren generieren SDKs basierend auf den Informationen in den .gql-Dateien (insbesondere schema.gql, queries.gql, mutations.gql) und der connector.yaml-Datei. Diese SDKs können direkt in Ihrer Anwendung aufgerufen werden.

  1. Entfernen Sie die Auskommentierung der Importanweisung oben in MovieService (app/src/lib/MovieService.tsx):
    import { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect";
    
    Die Funktion listMovies, der Antworttyp ListMoviesData und die Enumeration OrderDirection sind alle SDKs, die von den Firebase Data Connect-Emulatoren basierend auf dem Schema und den zuvor definierten Abfragen generiert wurden .
  2. Ersetzen Sie die Funktionen handleGetTopMovies und handleGetLatestMovies durch den folgenden Code:
    // Fetch top-rated movies
    export const handleGetTopMovies = async (
      limit: number
    ): Promise<ListMoviesData["movies"] | null> => {
      try {
        const response = await listMovies({
          orderByRating: OrderDirection.DESC,
          limit,
        });
        return response.data.movies;
      } catch (error) {
        console.error("Error fetching top movies:", error);
        return null;
      }
    };
    
    // Fetch latest movies
    export const handleGetLatestMovies = async (
      limit: number
    ): Promise<ListMoviesData["movies"] | null> => {
      try {
        const response = await listMovies({
          orderByReleaseYear: OrderDirection.DESC,
          limit,
        });
        return response.data.movies;
      } catch (error) {
        console.error("Error fetching latest movies:", error);
        return null;
      }
    };
    

Zusammenfassung

  • listMovies:Eine automatisch generierte Funktion, die die listMovies-Abfrage aufruft, um eine Liste von Filmen abzurufen. Sie enthält Optionen zum Sortieren nach Bewertung oder Erscheinungsjahr und zum Begrenzen der Anzahl der Ergebnisse.
  • ListMoviesData:Der Ergebnistyp, der verwendet wird, um die 10 besten und neuesten Filme auf der Startseite der App anzuzeigen.

Beispiele ansehen

Aktualisieren Sie Ihre Web-App, um die Abfrage in Aktion zu sehen. Auf der Startseite wird jetzt dynamisch die Liste der Filme angezeigt, wobei die Daten direkt aus Ihrer lokalen Datenbank abgerufen werden. Die am besten bewerteten und neuesten Filme werden nahtlos angezeigt und spiegeln die Daten wider, die Sie gerade eingerichtet haben.

6. Filmdetails und Schauspielerdetails anzeigen

In diesem Abschnitt implementieren Sie die Funktion zum Abrufen detaillierter Informationen zu einem Film oder Schauspieler anhand der jeweiligen eindeutigen ID. Dazu gehört nicht nur das Abrufen von Daten aus den jeweiligen Tabellen, sondern auch das Verknüpfen verwandter Tabellen, um umfassende Details wie Filmbesprechungen und Filmografien von Schauspielern anzuzeigen.

ac7fefa7ff779231.png

Connectors implementieren

  1. Öffnen Sie dataconnect/movie-connector/queries.gql in Ihrem Projekt.
  2. Fügen Sie die folgenden Abfragen hinzu, um Film- und Schauspielerin-/Schauspielerdetails abzurufen:
    # Get movie by id
    query GetMovieById($id: UUID!) @auth(level: PUBLIC) {
    movie(id: $id) {
        id
        title
        imageUrl
        releaseYear
        genre
        rating
        description
        tags
        metadata: movieMetadatas_on_movie {
          director
        }
        mainActors: actors_via_MovieActor(where: { role: { eq: "main" } }) {
          id
          name
          imageUrl
        }
        supportingActors: actors_via_MovieActor(
          where: { role: { eq: "supporting" } }
        ) {
          id
          name
          imageUrl
        }
        reviews: reviews_on_movie {
          id
          reviewText
          reviewDate
          rating
          user {
            id
            username
          }
        }
      }
    }
    
    # Get actor by id
    query GetActorById($id: UUID!) @auth(level: PUBLIC) {
      actor(id: $id) {
        id
        name
        imageUrl
        mainActors: movies_via_MovieActor(where: { role: { eq: "main" } }) {
          id
          title
          genre
          tags
          imageUrl
        }
        supportingActors: movies_via_MovieActor(
          where: { role: { eq: "supporting" } }
        ) {
          id
          title
          genre
          tags
          imageUrl
        }
      }
    }
    
  3. Speichern Sie die Änderungen und überprüfen Sie die Anfragen.

Zusammenfassung

  • movie()/actor(): GraphQL-Abfragefelder zum Abrufen eines einzelnen Films oder Schauspielers aus der Tabelle Movies oder Actors.
  • _on_: Dies ermöglicht den direkten Zugriff auf Felder eines zugehörigen Typs mit einer Fremdschlüsselbeziehung. Mit reviews_on_movie werden beispielsweise alle Rezensionen zu einem bestimmten Film abgerufen.
  • _via_: Wird verwendet, um n:m-Beziehungen über eine Join-Tabelle zu durchlaufen. Beispielsweise greift actors_via_MovieActor über die Join-Tabelle MovieActor auf den Typ Actor zu und mit der Bedingung where werden Schauspieler nach ihrer Rolle gefiltert (z. B. „main“ oder „supporting“).

Abfrage mit Scheindaten testen

  1. Im Bereich „Data Connect-Ausführung“ können Sie die Abfrage testen, indem Sie Mock-IDs eingeben, z. B.:
    {"id": "550e8400-e29b-41d4-a716-446655440000"}
    
  2. Klicken Sie für GetMovieById auf Run (local), um die Details zu „Quantum Paradox“ (dem fiktiven Film, auf den sich die oben genannte ID bezieht) abzurufen.

1b08961891e44da2.png

Anfragen in die Web-App einbinden

  1. Entfernen Sie das Kommentarzeichen bei den folgenden Importen in MovieService (app/src/lib/MovieService.tsx):
    import { getMovieById, GetMovieByIdData } from "@movie/dataconnect";
    import { GetActorByIdData, getActorById } from "@movie/dataconnect";
    
  2. Ersetzen Sie die Funktionen handleGetMovieById und handleGetActorById durch den folgenden Code:
    // Fetch movie details by ID
    export const handleGetMovieById = async (
      movieId: string
    ) => {
      try {
        const response = await getMovieById({ id: movieId });
        if (response.data.movie) {
          return response.data.movie;
        }
        return null;
      } catch (error) {
        console.error("Error fetching movie:", error);
        return null;
      }
    };
    
    // Calling generated SDK for GetActorById
    export const handleGetActorById = async (
      actorId: string
    ): Promise<GetActorByIdData["actor"] | null> => {
      try {
        const response = await getActorById({ id: actorId });
        if (response.data.actor) {
          return response.data.actor;
        }
        return null;
      } catch (error) {
        console.error("Error fetching actor:", error);
        return null;
      }
    };
    

Zusammenfassung

  • getMovieById / getActorById: Dies sind automatisch generierte Funktionen, die die von Ihnen definierten Abfragen aufrufen und detaillierte Informationen zu einem bestimmten Film oder Schauspieler abrufen.
  • GetMovieByIdData / GetActorByIdData: Dies sind die Ergebnistypen, die zum Anzeigen von Film- und Schauspielerin-/Schauspielerdetails in der App verwendet werden.

Beispiele ansehen

Rufen Sie nun die Startseite Ihrer Web-App auf. Wenn Sie auf einen Film klicken, werden alle Details dazu angezeigt, einschließlich der Schauspieler und Rezensionen. Diese Informationen stammen aus verknüpften Tabellen. Wenn Sie auf einen Schauspieler klicken, werden die Filme angezeigt, in denen er mitgespielt hat.

7. Nutzerauthentifizierung verarbeiten

In diesem Abschnitt implementieren Sie die Funktionen zum An- und Abmelden von Nutzern mit Firebase Authentication. Sie verwenden Firebase Authentication-Daten auch, um Nutzerdaten direkt in Firebase DataConnect abzurufen oder einzufügen. So ist eine sichere Nutzerverwaltung in Ihrer App gewährleistet.

9890838045d5a00e.png

Connectors implementieren

  1. mutations.gql in dataconnect/movie-connector/ öffnen
  2. Fügen Sie die folgende Mutation hinzu, um den aktuell authentifizierten Nutzer zu erstellen oder zu aktualisieren:
    # Create or update the current authenticated user
    mutation UpsertUser($username: String!) @auth(level: USER) {
      user_upsert(
        data: {
          id_expr: "auth.uid"
          username: $username
        }
      )
    }
    

Zusammenfassung

  • id_expr: "auth.uid": Hier wird auth.uid verwendet, das direkt von Firebase Authentication bereitgestellt wird, nicht vom Nutzer oder der App. So wird eine zusätzliche Sicherheitsebene geschaffen, da die Nutzer-ID sicher und automatisch verarbeitet wird.

Aktuellen Nutzer abrufen

  1. queries.gql in dataconnect/movie-connector/ öffnen
  2. Fügen Sie die folgende Abfrage hinzu, um den aktuellen Nutzer abzurufen:
    # Get user by ID
    query GetCurrentUser @auth(level: USER) {
      user(key: { id_expr: "auth.uid" }) {
        id
        username
        reviews: reviews_on_user {
          id
          rating
          reviewDate
          reviewText
          movie {
            id
            title
          }
        }
        favoriteMovies: favorite_movies_on_user {
          movie {
            id
            title
            genre
            imageUrl
            releaseYear
            rating
            description
            tags
            metadata: movieMetadatas_on_movie {
              director
            }
          }
        }
      }
    }
    

Zusammenfassung

  • auth.uid: Dieser Wert wird direkt von Firebase Authentication abgerufen, um einen sicheren Zugriff auf nutzerspezifische Daten zu gewährleisten.
  • _on_-Felder: Diese Felder stellen die Join-Tabellen dar:
    • reviews_on_user: Ruft alle Rezensionen ab, die sich auf den Nutzer beziehen, einschließlich der id und title des Films.
    • favorite_movies_on_user: Ruft alle Filme ab, die vom Nutzer als Favoriten markiert wurden, einschließlich detaillierter Informationen wie genre, releaseYear, rating und metadata.

Anfragen in die Webanwendung einbinden

  1. Entfernen Sie in MovieService (app/src/lib/MovieService.tsx) die Auskommentierung der folgenden Importe:
    import { upsertUser } from "@movie/dataconnect";
    import { getCurrentUser, GetCurrentUserData } from "@movie/dataconnect";
    
  2. Ersetzen Sie die Funktionen handleAuthStateChange und handleGetCurrentUser durch den folgenden Code:
    // Handle user authentication state changes and upsert user
    export const handleAuthStateChange = (
      auth: any,
      setUser: (user: User | null) => void
    ) => {
      return onAuthStateChanged(auth, async (user) => {
        if (user) {
          setUser(user);
          const username = user.email?.split("@")[0] || "anon";
          await upsertUser({ username });
        } else {
          setUser(null);
        }
      });
    };
    
    // Fetch current user profile
    export const handleGetCurrentUser = async (): Promise<
      GetCurrentUserData["user"] | null
    > => {
      try {
        const response = await getCurrentUser();
        return response.data.user;
      } catch (error) {
        console.error("Error fetching user profile:", error);
        return null;
      }
    };
    

Zusammenfassung

  • handleAuthStateChange: Diese Funktion überwacht Änderungen des Authentifizierungsstatus. Wenn sich ein Nutzer anmeldet, werden seine Daten festgelegt und die upsertUser-Mutation wird aufgerufen, um die Informationen des Nutzers in der Datenbank zu erstellen oder zu aktualisieren.
  • handleGetCurrentUser: Ruft das Profil des aktuellen Nutzers mit der getCurrentUser-Abfrage ab, mit der die Rezensionen und Lieblingsfilme des Nutzers abgerufen werden.

Beispiele ansehen

Klicken Sie nun in der Navigationsleiste auf die Schaltfläche „Über Google anmelden“. Sie können sich mit dem Firebase Authentication-Emulator anmelden. Klicken Sie nach der Anmeldung auf „Mein Profil“. Sie ist jetzt noch leer, aber Sie haben die Grundlage für die nutzerspezifische Datenverarbeitung in Ihrer App geschaffen.

8. Nutzerinteraktionen implementieren

In diesem Abschnitt des Codelabs implementieren Sie Nutzerinteraktionen in der Filmkritik-App. Nutzer sollen ihre Lieblingsfilme verwalten und Rezensionen hinterlassen oder löschen können.

b3d0ac1e181c9de9.png

Nutzer können Filme als Favoriten markieren

In diesem Abschnitt richten Sie die Datenbank so ein, dass Nutzer Filme als Favoriten markieren können.

Connectors implementieren

  1. mutations.gql in dataconnect/movie-connector/ öffnen
  2. Fügen Sie die folgenden Mutationen hinzu, um das Markieren von Filmen als Favoriten zu ermöglichen:
    # Add a movie to the user's favorites list
    mutation AddFavoritedMovie($movieId: UUID!) @auth(level: USER) {
      favorite_movie_upsert(data: { userId_expr: "auth.uid", movieId: $movieId })
    }
    
    # Remove a movie from the user's favorites list
    mutation DeleteFavoritedMovie($movieId: UUID!) @auth(level: USER) {
      favorite_movie_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
    }
    
    

Zusammenfassung

  • userId_expr: "auth.uid": Hier wird auth.uid verwendet, das direkt von Firebase Authentication bereitgestellt wird. So wird sichergestellt, dass nur auf die Daten des authentifizierten Nutzers zugegriffen oder diese geändert werden.

Prüfen, ob ein Film als Favorit markiert ist

  1. queries.gql in dataconnect/movie-connector/ öffnen
  2. Fügen Sie die folgende Abfrage hinzu, um zu prüfen, ob ein Film als Favorit markiert ist:
    query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
      favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
        movieId
      }
    }
    

Zusammenfassung

  • auth.uid: Sorgt für sicheren Zugriff auf nutzerspezifische Daten mit Firebase Authentication.
  • favorite_movie: Prüft in der Verknüpfungstabelle favorite_movies, ob ein bestimmter Film vom aktuellen Nutzer als Favorit markiert ist.

Anfragen in die Web-App einbinden

  1. Entfernen Sie das Kommentarzeichen bei den folgenden Importen in MovieService (app/src/lib/MovieService.tsx):
    import { addFavoritedMovie, deleteFavoritedMovie, getIfFavoritedMovie } from "@movie/dataconnect";
    
  2. Ersetzen Sie die Funktionen handleAddFavoritedMovie, handleDeleteFavoritedMovie und handleGetIfFavoritedMovie durch den folgenden Code:
    // Add a movie to user's favorites
    export const handleAddFavoritedMovie = async (
      movieId: string
    ): Promise<void> => {
      try {
        await addFavoritedMovie({ movieId });
      } catch (error) {
        console.error("Error adding movie to favorites:", error);
        throw error;
      }
    };
    
    // Remove a movie from user's favorites
    export const handleDeleteFavoritedMovie = async (
      movieId: string
    ): Promise<void> => {
      try {
        await deleteFavoritedMovie({ movieId });
      } catch (error) {
        console.error("Error removing movie from favorites:", error);
        throw error;
      }
    };
    
    // Check if the movie is favorited by the user
    export const handleGetIfFavoritedMovie = async (
      movieId: string
    ): Promise<boolean> => {
      try {
        const response = await getIfFavoritedMovie({ movieId });
        return !!response.data.favorite_movie;
      } catch (error) {
        console.error("Error checking if movie is favorited:", error);
        return false;
      }
    };
    

Zusammenfassung

  • handleAddFavoritedMovie und handleDeleteFavoritedMovie: Mit den Mutationen können Sie einen Film sicher zu den Favoriten des Nutzers hinzufügen oder daraus entfernen.
  • handleGetIfFavoritedMovie: Verwendet die getIfFavoritedMovie-Abfrage, um zu prüfen, ob ein Film vom Nutzer als Favorit markiert wurde.

Beispiele ansehen

Sie können Filme jetzt als Favoriten markieren oder die Markierung aufheben, indem Sie auf den Filmkarten und auf der Filmdetailseite auf das Herzsymbol klicken. Außerdem können Sie sich Ihre Lieblingsfilme auf Ihrer Profilseite ansehen.

Nutzern erlauben, Rezensionen zu hinterlassen oder zu löschen

Als Nächstes implementieren Sie den Abschnitt zum Verwalten von Nutzerrezensionen in der App.

Connectors implementieren

Fügen Sie in mutations.gql (dataconnect/movie-connector/mutations.gql) die folgenden Mutationen hinzu:

# Add a review for a movie
mutation AddReview($movieId: UUID!, $rating: Int!, $reviewText: String!)
@auth(level: USER) {
  review_insert(
    data: {
      userId_expr: "auth.uid"
      movieId: $movieId
      rating: $rating
      reviewText: $reviewText
      reviewDate_date: { today: true }
    }
  )
}

# Delete a user's review for a movie
mutation DeleteReview($movieId: UUID!) @auth(level: USER) {
  review_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
}

Zusammenfassung

  • userId_expr: "auth.uid": Sorgt dafür, dass Rezensionen dem authentifizierten Nutzer zugeordnet werden.
  • reviewDate_date: { today: true }: Das aktuelle Datum für die Rezension wird automatisch mit DataConnect generiert. Eine manuelle Eingabe ist nicht erforderlich.

Anfragen in die Web-App einbinden

  1. Entfernen Sie das Kommentarzeichen bei den folgenden Importen in MovieService (app/src/lib/MovieService.tsx):
    import { addReview, deleteReview } from "@movie/dataconnect";
    
  2. Ersetzen Sie die Funktionen handleAddReview und handleDeleteReview durch den folgenden Code:
    // Add a review to a movie
    export const handleAddReview = async (
      movieId: string,
      rating: number,
      reviewText: string
    ): Promise<void> => {
      try {
        await addReview({ movieId, rating, reviewText });
      } catch (error) {
        console.error("Error adding review:", error);
        throw error;
      }
    };
    
    // Delete a review from a movie
    export const handleDeleteReview = async (movieId: string): Promise<void> => {
      try {
        await deleteReview({ movieId });
      } catch (error) {
        console.error("Error deleting review:", error);
        throw error;
      }
    };
    

Zusammenfassung

  • handleAddReview: Ruft die Mutation addReview auf, um eine Rezension für den angegebenen Film hinzuzufügen und sie sicher mit dem authentifizierten Nutzer zu verknüpfen.
  • handleDeleteReview: Verwendet die Mutation deleteReview, um eine Rezension für einen Film durch den authentifizierten Nutzer zu entfernen.

Beispiele ansehen

Nutzer können jetzt auf der Detailseite eines Films Rezensionen schreiben. Außerdem können sie ihre Rezensionen auf ihrer Profilseite ansehen und löschen. So haben sie die volle Kontrolle über ihre Interaktionen mit der App.

9. Erweiterte Filter und teilweiser Textabgleich

In diesem Abschnitt implementieren Sie erweiterte Suchfunktionen, mit denen Nutzer Filme anhand einer Reihe von Altersfreigaben und Erscheinungsjahren suchen, nach Genres und Tags filtern, teilweise Textübereinstimmungen in Titeln oder Beschreibungen durchführen und sogar mehrere Filter für genauere Ergebnisse kombinieren können.

ece70ee0ab964e28.png

Connectors implementieren

  1. Öffnen Sie queries.gql in dataconnect/movie-connector/.
  2. Fügen Sie die folgende Abfrage hinzu, um verschiedene Suchfunktionen zu unterstützen: Add
    # Search for movies, actors, and reviews
    query SearchAll(
      $input: String
      $minYear: Int!
      $maxYear: Int!
      $minRating: Float!
      $maxRating: Float!
      $genre: String!
    ) @auth(level: PUBLIC) {
      moviesMatchingTitle: movies(
        where: {
          _and: [
            { releaseYear: { ge: $minYear } }
            { releaseYear: { le: $maxYear } }
            { rating: { ge: $minRating } }
            { rating: { le: $maxRating } }
            { genre: { contains: $genre } }
            { title: { contains: $input } }
          ]
        }
      ) {
        id
        title
        genre
        rating
        imageUrl
      }
      moviesMatchingDescription: movies(
        where: {
          _and: [
            { releaseYear: { ge: $minYear } }
            { releaseYear: { le: $maxYear } }
            { rating: { ge: $minRating } }
            { rating: { le: $maxRating } }
            { genre: { contains: $genre } }
            { description: { contains: $input } }
          ]
        }
      ) {
        id
        title
        genre
        rating
        imageUrl
      }
      actorsMatchingName: actors(where: { name: { contains: $input } }) {
        id
        name
        imageUrl
      }
      reviewsMatchingText: reviews(where: { reviewText: { contains: $input } }) {
        id
        rating
        reviewText
        reviewDate
        movie {
          id
          title
        }
        user {
          id
          username
        }
      }
    }
    

Zusammenfassung

  • Operator _and: Kombiniert mehrere Bedingungen in einer einzelnen Abfrage, sodass die Suche nach mehreren Feldern wie releaseYear, rating und genre gefiltert werden kann.
  • Operator contains: Sucht nach teilweisen Textübereinstimmungen in Feldern. In dieser Abfrage wird nach Übereinstimmungen in title, description, name oder reviewText gesucht.
  • where-Klausel: Gibt die Bedingungen zum Filtern von Daten an. In jedem Abschnitt (Filme, Schauspieler, Rezensionen) wird mit einer where-Klausel das spezifische Kriterium für die Suche definiert.

Anfragen in die Web-App einbinden

  1. Entfernen Sie das Kommentarzeichen bei den folgenden Importen in MovieService (app/src/lib/MovieService.tsx):
    import { searchAll, SearchAllData } from "@movie/dataconnect";
    
  2. Ersetzen Sie die Funktion handleSearchAll durch den folgenden Code:
    // Function to perform the search using the query and filters
    export const handleSearchAll = async (
      searchQuery: string,
      minYear: number,
      maxYear: number,
      minRating: number,
      maxRating: number,
      genre: string
    ): Promise<SearchAllData | null> => {
      try {
        const response = await searchAll({
          input: searchQuery,
          minYear,
          maxYear,
          minRating,
          maxRating,
          genre,
        });
    
        return response.data;
      } catch (error) {
        console.error("Error performing search:", error);
        return null;
      }
    };
    

Zusammenfassung

  • handleSearchAll: Diese Funktion verwendet die searchAll-Abfrage, um eine Suche basierend auf der Eingabe des Nutzers durchzuführen und die Ergebnisse nach Parametern wie Jahr, Bewertung, Genre und Teiltextübereinstimmungen zu filtern.

Beispiele ansehen

Rufen Sie in der Web-App über die Navigationsleiste die Seite „Erweiterte Suche“ auf. Sie können jetzt mit verschiedenen Filtern und Eingaben nach Filmen, Schauspielern und Rezensionen suchen und erhalten detaillierte und maßgeschneiderte Suchergebnisse.

10. Optional: In der Cloud bereitstellen (Abrechnung erforderlich)

Nachdem Sie die lokale Entwicklung durchlaufen haben, ist es an der Zeit, Ihr Schema, Ihre Daten und Ihre Abfragen auf dem Server bereitzustellen. Das ist mit der VS Code-Erweiterung für Firebase Data Connect oder der Firebase CLI möglich.

Firebase-Tarif upgraden

Damit Sie Firebase Data Connect in Cloud SQL for PostgreSQL einbinden können, muss Ihr Firebase-Projekt den Blaze-Tarif (Pay as you go) verwenden. Das bedeutet, dass es mit einem Cloud-Rechnungskonto verknüpft ist.

  • Für ein Cloud-Rechnungskonto ist eine Zahlungsmethode wie eine Kreditkarte erforderlich.
  • Wenn Sie neu bei Firebase und Google Cloud sind, können Sie prüfen, ob Sie Anspruch auf ein Guthaben von 300$und ein Cloud-Rechnungskonto für den kostenlosen Testzeitraum haben.
  • Wenn Sie dieses Codelab im Rahmen einer Veranstaltung durchführen, fragen Sie den Organisator, ob Cloud-Guthaben verfügbar ist.

So führen Sie für Ihr Projekt ein Upgrade auf den Tarif „Blaze“ durch:

  1. Wählen Sie in der Firebase Console die Option zum Upgraden Ihres Abos aus.
  2. Wählen Sie den Blaze-Tarif aus. Folgen Sie der Anleitung auf dem Bildschirm, um ein Cloud-Rechnungskonto mit Ihrem Projekt zu verknüpfen.
    Wenn Sie im Rahmen dieses Upgrades ein Cloud-Rechnungskonto erstellen mussten, müssen Sie möglicherweise zur Firebase-Konsole zurückkehren, um das Upgrade abzuschließen.

Web-App mit Firebase-Projekt verknüpfen

  1. Registrieren Sie Ihre Web-App in Ihrem Firebase-Projekt über die Firebase Console:
    1. Öffnen Sie Ihr Projekt und klicken Sie auf App hinzufügen.
    2. Ignorieren Sie vorerst die SDK-Einrichtung und -Konfiguration, kopieren Sie aber das generierte firebaseConfig-Objekt.
    7030822793e4d75b.png
  2. Ersetzen Sie die vorhandene firebaseConfig in app/src/lib/firebase.tsx durch die Konfiguration, die Sie gerade aus der Firebase Console kopiert haben.
    const firebaseConfig = {
      apiKey: "API_KEY",
      authDomain: "PROJECT_ID.firebaseapp.com",
      projectId: "PROJECT_ID",
      storageBucket: "PROJECT_ID.firebasestorage.app",
      messagingSenderId: "SENDER_ID",
      appId: "APP_ID"
    };
    
  3. Web-App erstellen:Verwenden Sie in VS Code im Ordner app Vite, um die Web-App für die Hosting-Bereitstellung zu erstellen:
    cd app
    npm run build
    

Firebase Authentication in Ihrem Firebase-Projekt einrichten

  1. Richten Sie Firebase Authentication mit Google Sign-in ein.62af2f225e790ef6.png
  2. (Optional) Erlauben Sie Domains für Firebase Authentication über die Firebase Console (z. B. http://127.0.0.1).
    1. Rufen Sie in den Authentifizierungseinstellungen die autorisierten Domains auf.
    2. Klicken Sie auf „Domain hinzufügen“ und fügen Sie Ihre lokale Domain in die Liste ein.

c255098f12549886.png

Mit der Firebase CLI bereitstellen

  1. Achten Sie in dataconnect/dataconnect.yaml darauf, dass die Instanz-ID, die Datenbank und die Dienst-ID mit Ihrem Projekt übereinstimmen:
    specVersion: "v1alpha"
    serviceId: "your-service-id"
    location: "us-central1"
    schema:
      source: "./schema"
      datasource:
        postgresql:
          database: "your-database-id"
          cloudSql:
            instanceId: "your-instance-id"
    connectorDirs: ["./movie-connector"]
    
  2. Achten Sie darauf, dass die Firebase CLI für Ihr Projekt eingerichtet ist:
    npm i -g firebase-tools
    firebase login --reauth
    firebase use --add
    
  3. Führen Sie im Terminal den folgenden Befehl aus, um die Bereitstellung vorzunehmen:
    firebase deploy --only dataconnect,hosting
    
  4. Führen Sie diesen Befehl aus, um Ihre Schemaänderungen zu vergleichen:
    firebase dataconnect:sql:diff
    
  5. Wenn die Änderungen akzeptabel sind, wenden Sie sie mit folgendem Befehl an:
    firebase dataconnect:sql:migrate
    

Ihre Cloud SQL for PostgreSQL-Instanz wird mit dem endgültigen bereitgestellten Schema und den endgültigen bereitgestellten Daten aktualisiert. Sie können den Status in der Firebase Console überwachen.

Sie sollten Ihre App jetzt unter your-project.web.app/ live sehen können. Außerdem können Sie im Bereich „Firebase Data Connect“ auf Ausführen (Produktion) klicken, um Daten in die Produktionsumgebung einzufügen.

11. Optional: Vektorsuche mit Firebase Data Connect (Abrechnung erforderlich)

In diesem Abschnitt aktivieren Sie die Vektorsuche in Ihrer App für Filmbesprechungen mit Firebase Data Connect. Mit dieser Funktion können Sie inhaltsbezogene Suchen durchführen, z. B. Filme mit ähnlichen Beschreibungen mithilfe von Vektoreinbettungen finden.

Für diesen Schritt müssen Sie den letzten Schritt dieses Codelabs abgeschlossen haben, um die Bereitstellung in Google Cloud durchzuführen.

4b5aca5a447d2feb.png

Schema aktualisieren, um Einbettungen für ein Feld einzuschließen

Fügen Sie in dataconnect/schema/schema.gql der Tabelle Movie das Feld descriptionEmbedding hinzu:

type Movie
  # The below parameter values are generated by default with @table, and can be edited manually.
  @table {
  # implicitly calls @col to generates a column name. ex: @col(name: "movie_id")
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  imageUrl: String!
  releaseYear: Int
  genre: String
  rating: Float
  description: String
  tags: [String]
  descriptionEmbedding: Vector @col(size:768) # Enables vector search
}

Zusammenfassung

  • descriptionEmbedding: Vector @col(size:768): In diesem Feld werden die semantischen Einbettungen von Filmbeschreibungen gespeichert, um eine vektorbasierte Inhaltssuche in Ihrer App zu ermöglichen.

Vertex AI aktivieren

  1. Folgen Sie der Anleitung zu den Voraussetzungen, um Vertex AI APIs über Google Cloud einzurichten. Dieser Schritt ist wichtig, um die Funktionen zum Generieren von Einbettungen und zur Vektorsuche zu unterstützen.
  2. Stellen Sie Ihr Schema noch einmal bereit, um pgvector und die Vektorsuche zu aktivieren. Klicken Sie dazu mit der Firebase Data Connect VS Code-Erweiterung auf „In Produktion bereitstellen“.

Datenbank mit Einbettungen füllen

  1. Öffnen Sie den Ordner dataconnect in VS Code.
  2. Klicken Sie in optional_vector_embed.gql auf Run(local), um Ihre Datenbank mit Einbettungen für die Filme zu füllen.

b858da780f6ec103.png

Vektorsuche hinzufügen

Fügen Sie in dataconnect/movie-connector/queries.gql die folgende Abfrage hinzu, um Vektorsuchen auszuführen:

# Search movie descriptions using L2 similarity with Vertex AI
query SearchMovieDescriptionUsingL2Similarity($query: String!)
@auth(level: PUBLIC) {
  movies_descriptionEmbedding_similarity(
    compare_embed: { model: "textembedding-gecko@003", text: $query }
    method: L2
    within: 2
    limit: 5
  ) {
    id
    title
    description
    tags
    rating
    imageUrl
  }
}

Zusammenfassung

  • compare_embed: Gibt das Einbettungsmodell (textembedding-gecko@003) und den Eingabetext ($query) für den Vergleich an.
  • method: Gibt die Ähnlichkeitsmethode (L2) an, die die euklidische Distanz darstellt.
  • within: Beschränkt die Suche auf Filme mit einem L2-Abstand von höchstens 2, wobei der Fokus auf ähnlichen Inhalten liegt.
  • limit: Beschränkt die Anzahl der zurückgegebenen Ergebnisse auf 5.

Vektorsuchfunktion in Ihre App einbinden

Nachdem Sie das Schema und die Abfrage eingerichtet haben, können Sie die Vektorsuche in die Dienstschicht Ihrer App einbinden. Mit diesem Schritt können Sie die Suchanfrage aus Ihrer Web-App aufrufen.

  1. Entfernen Sie in app/src/lib/ MovieService.ts die Auskommentierung der folgenden Importe aus den SDKs. Das funktioniert wie jede andere Anfrage.
    import {
      searchMovieDescriptionUsingL2similarity,
      SearchMovieDescriptionUsingL2similarityData,
    } from "@movie/dataconnect";
    
  2. Fügen Sie die folgende Funktion hinzu, um die vektorbasierte Suche in die App einzubinden:
    // Perform vector-based search for movies based on description
    export const searchMoviesByDescription = async (
      query: string
    ): Promise<
      | SearchMovieDescriptionUsingL2similarityData["movies_descriptionEmbedding_similarity"]
      | null
    > => {
      try {
        const response = await searchMovieDescriptionUsingL2similarity({ query });
        return response.data.movies_descriptionEmbedding_similarity;
      } catch (error) {
        console.error("Error fetching movie descriptions:", error);
        return null;
      }
    };
    

Zusammenfassung

  • searchMoviesByDescription: Diese Funktion ruft die searchMovieDescriptionUsingL2similarity-Abfrage auf und übergibt den Eingabetext, um eine vektorbasierte Inhaltssuche durchzuführen.

Beispiele ansehen

Gehen Sie in der Navigationsleiste zum Bereich „Vector Search“ (Vektorsuche) und geben Sie Begriffe wie „romantisch und modern“ ein. Sie sehen eine Liste von Filmen, die den gesuchten Inhalten entsprechen. Alternativ können Sie auch die Detailseite eines beliebigen Films aufrufen und sich unten auf der Seite den Bereich „Ähnliche Filme“ ansehen.

7b71f1c75633c1be.png

12. Fazit

Glückwunsch! Sie sollten die Web-App jetzt verwenden können. Wenn Sie Ihre eigenen Filmdaten verwenden möchten, können Sie sie mit der Firebase Data Connect-Erweiterung einfügen. Dazu müssen Sie die _insert.gql-Dateien nachahmen oder die Daten über den Data Connect-Ausführungsbereich in VS Code hinzufügen.

Weitere Informationen