Firebase Data Connect ile oluşturma (web)

1. Başlamadan önce

FriendlyMovies uygulaması

Bu codelab'de, film incelemesi web uygulaması oluşturmak için Firebase Data Connect'i Cloud SQL veritabanıyla entegre edeceksiniz. Tamamlanan uygulama, Firebase Data Connect'in SQL destekli uygulamalar oluşturma sürecini nasıl basitleştirdiğini gösterir. Bu ortamda aşağıdaki özellikler sunulur:

  • Kimlik doğrulama: Uygulamanızın sorguları ve mutasyonları için özel kimlik doğrulama uygulayarak yalnızca yetkili kullanıcıların verilerinizle etkileşim kurabilmesini sağlayın.
  • GraphQL şeması: Film inceleme web uygulamasının ihtiyaçlarına göre uyarlanmış esnek bir GraphQL şeması kullanarak veri yapılarınızı oluşturun ve yönetin.
  • SQL sorguları ve mutasyonları: GraphQL destekli sorgular ve mutasyonlar kullanarak Cloud SQL'deki verileri alın, güncelleyin ve yönetin.
  • Kısmi dize eşleşmesiyle gelişmiş arama: Başlık, açıklama veya etiketler gibi alanlara göre film bulmak için filtreleri ve arama seçeneklerini kullanın.
  • (İsteğe bağlı) Vektör arama entegrasyonu: Giriş ve tercihlere dayalı zengin bir kullanıcı deneyimi sunmak için Firebase Data Connect'in vektör arama özelliğini kullanarak içerik arama işlevi ekleyin.

Ön koşullar

JavaScript hakkında temel bilgilere sahip olmanız gerekir.

Neler öğreneceksiniz?

  • Firebase Data Connect'i yerel emülatörlerle ayarlayın.
  • Data Connect ve GraphQL kullanarak veri şeması tasarlama
  • Bir film inceleme uygulaması için çeşitli sorgular ve mutasyonlar yazıp test etme
  • Firebase Data Connect'in uygulamada SDK'yı nasıl oluşturduğunu ve kullandığını öğrenin.
  • Şemanızı dağıtın ve veritabanını verimli bir şekilde yönetin.

Gerekenler

2. Geliştirme ortamınızı kurma

Codelab'in bu aşamasında, Firebase Data Connect'i kullanarak film inceleme uygulamanızı oluşturmaya başlamak için ortamı ayarlama konusunda size yol gösterilecektir.

  1. Proje deposunu klonlayın ve gerekli bağımlılıkları yükleyin:
    git clone https://github.com/firebaseextended/codelab-dataconnect-web
    cd codelab-dataconnect-web
    cd ./app && npm i
    npm run dev
    
  2. Bu komutları çalıştırdıktan sonra, web uygulamasının yerel olarak çalıştığını görmek için tarayıcınızda http://localhost:5173 adresini açın. Bu, film inceleme uygulamasını oluşturmak ve özellikleriyle etkileşim kurmak için ön uç görevi görür.93f6648a2532c606.png
  3. Visual Studio Code'u kullanarak klonlanan codelab-dataconnect-web klasörünü açın. Şemanızı tanımlayacağınız, sorgu yazacağınız ve uygulamanın işlevselliğini test edeceğiniz yer burasıdır.
  4. Veri Bağlantısı özelliklerini kullanmak için Firebase Data Connect Visual Studio Uzantısı'nı yükleyin.
    Alternatif olarak, uzantıyı Visual Studio Code Marketplace'ten yükleyebilir veya VS Code'da arayabilirsiniz.b03ee38c9a81b648.png
  5. Firebase konsolunda yeni bir Firebase projesi açın veya oluşturun.
  6. Firebase projenizi Firebase Data Connect VSCode uzantısına bağlayın. Uzantıda aşağıdakileri yapın:
    1. Oturum aç düğmesini tıklayın.
    2. Firebase projesi bağla'yı tıklayın ve Firebase projenizi seçin.
    4bb2fbf8f9fac29b.png
  7. Firebase Data Connect VS Code uzantısını kullanarak Firebase emülatörlerini başlatın:
    Start Emulators'ı (Emülatörleri Başlat) tıklayın ve emülatörlerin terminalde çalıştığını onaylayın.6d3d95f4cb708db1.png

3. Başlangıç kod tabanını inceleme

Bu bölümde, uygulamanın başlangıç kod tabanının temel alanlarını keşfedeceksiniz. Uygulamada bazı işlevler eksik olsa da genel yapıyı anlamak için faydalıdır.

Klasör ve dosya yapısı

Aşağıdaki alt bölümlerde, uygulamanın klasör ve dosya yapısına genel bir bakış sunulmaktadır.

dataconnect/ dizini

Firebase Data Connect yapılandırmalarını, bağlayıcıları (sorguları ve mutasyonları tanımlar) ve şema dosyalarını içerir.

  • schema/schema.gql: GraphQL şemasını tanımlar.
  • connector/queries.gql: Uygulamanızda gereken sorgular
  • connector/mutations.gql: Uygulamanızda yapılması gereken değişiklikler
  • connector/connector.yaml: SDK oluşturma için yapılandırma dosyası

app/src/ dizini

Uygulama mantığını ve Firebase Data Connect ile etkileşimi içerir.

  • firebase.ts: Firebase projenizdeki bir Firebase uygulamasına bağlanma yapılandırması.
  • lib/dataconnect-sdk/: Oluşturulan SDK'yı içerir. SDK oluşturma konumunu connector/connector.yaml dosyasında düzenleyebilirsiniz. Sorgu veya mutasyon tanımladığınızda SDK'lar otomatik olarak oluşturulur.

4. Film yorumları için şema tanımlama

Bu bölümde, film uygulamasındaki temel öğeler arasındaki yapıyı ve ilişkileri bir şemada tanımlayacaksınız. Movie, User, Actor ve Review gibi öğeler, Firebase Data Connect ve GraphQL şema yönergeleri kullanılarak oluşturulan ilişkilerle veritabanı tablolarına eşlenir. Bu özellik etkinleştirildikten sonra uygulamanız, en çok beğenilen filmleri aramaktan türlere göre filtrelemeye, kullanıcıların yorum bırakmasına, favori filmleri işaretlemesine, benzer filmleri keşfetmesine veya vektör araması aracılığıyla metin girişine dayalı olarak önerilen filmleri bulmasına kadar her şeyi yapmaya hazır olur.

Temel öğeler ve ilişkiler

Movie türü, uygulamanın aramalar ve film profilleri için kullandığı başlık, tür ve etiketler gibi önemli ayrıntıları içerir. User türü, yorumlar ve favoriler gibi kullanıcı etkileşimlerini izler. Reviews Kullanıcıları filmlere bağlayarak uygulamada kullanıcı tarafından oluşturulan puanların ve geri bildirimlerin gösterilmesine olanak tanır.

Filmler, aktörler ve kullanıcılar arasındaki ilişkiler uygulamayı daha dinamik hale getirir. MovieActor birleştirme tablosu, oyuncu ayrıntılarının ve filmografilerinin gösterilmesine yardımcı olur. FavoriteMovie türü, kullanıcıların filmleri favorilerine eklemesine olanak tanır. Böylece uygulama, kişiselleştirilmiş bir favoriler listesi gösterebilir ve popüler seçimleri öne çıkarabilir.

Movie tablosunu oluşturma

Movie türü, title, genre, releaseYear ve rating gibi alanlar da dahil olmak üzere bir film öğesinin ana yapısını tanımlar.

Kod snippet'ini dataconnect/schema/schema.gql dosyanıza kopyalayıp yapıştırın:

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

Temel Çıkarımlar:

  • id: @default(expr: "uuidV4()") kullanılarak oluşturulan, her film için benzersiz bir UUID.

MovieMetadata tablosunu oluşturma

MovieMetadata türü, Movie türüyle bire bir ilişki kurar. Film yönetmeni gibi ek veriler içerir.

Kod snippet'ini dataconnect/schema/schema.gql dosyanıza kopyalayıp yapıştırın:

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
}

Temel Çıkarımlar:

  • Movie! @ref: Yabancı anahtar ilişkisi oluşturarak Movie türüne referans verir.

Actor tablosunu oluşturma

Kod snippet'ini dataconnect/schema/schema.gql dosyanıza kopyalayıp yapıştırın:

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

Actor türü, film veritabanındaki bir aktörü temsil eder. Her aktör, birçok filmin parçası olabilir ve çoktan çoğa ilişki oluşturabilir.

MovieActor tablosunu oluşturma

Kod snippet'ini dataconnect/schema/schema.gql dosyanıza kopyalayıp yapıştırın:

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"
}

Temel Çıkarımlar:

  • movie: Film türüne referans verir ve yabancı anahtar movieId: UUID! öğesini örtülü olarak oluşturur.
  • actor: İşlem gerçekleştiren kullanıcı türüne referans verir ve yabancı anahtar actorId: UUID! öğesini örtülü olarak oluşturur.
  • role: Oyuncunun filmdeki rolünü tanımlar (ör. "main" veya "supporting").

User tablosunu oluşturma

User türü, yorum bırakarak veya filmleri favorilerine ekleyerek filmlerle etkileşimde bulunan bir kullanıcı öğesini tanımlar.

Kod snippet'ini dataconnect/schema/schema.gql dosyanıza kopyalayıp yapıştırın:

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 tablosunu oluşturma

FavoriteMovie türü, kullanıcılar ve en sevdikleri filmler arasındaki çoktan çoka ilişkileri işleyen bir birleştirme tablosudur. Her tablo, bir User ile bir Movie'yi birbirine bağlar.

Kod snippet'ini dataconnect/schema/schema.gql dosyanıza kopyalayıp yapıştırın:

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

Temel Çıkarımlar:

  • movie: Film türüne referans verir ve dolaylı olarak bir yabancı anahtar movieId: UUID! oluşturur.
  • user: Kullanıcı türüne referans verir ve yabancı anahtar userId: UUID!'ı dolaylı olarak oluşturur.

Review tablosunu oluşturma

Review türü, yorum öğesini temsil eder ve User ile Movie türlerini çoktan çoğa ilişkiyle bağlar (bir kullanıcı birçok yorum bırakabilir ve her film birçok yorum alabilir).

Kod snippet'ini dataconnect/schema/schema.gql dosyanıza kopyalayıp yapıştırın:

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")
}

Temel Çıkarımlar:

  • user: Yorumu bırakan kullanıcıyı ifade eder.
  • movie: İncelenen filme referans verir.
  • reviewDate: @default(expr: "request.time") kullanılarak yorum oluşturulduğunda otomatik olarak ayarlanır.

Otomatik olarak oluşturulan alanlar ve varsayılanlar

Şema, benzersiz kimlikleri ve zaman damgalarını otomatik olarak oluşturmak için @default(expr: "uuidV4()") gibi ifadeler kullanır. Örneğin, yeni bir kayıt oluşturulduğunda Movie ve Review türlerindeki id alanı otomatik olarak bir UUID ile doldurulur.

Şema tanımlandığına göre artık film uygulamanızın veri yapısı ve ilişkileri için sağlam bir temel var.

5. En iyi ve en yeni filmleri alma

FriendlyMovies uygulaması

Bu bölümde, yerel emülatörlere sahte film verileri ekleyecek, ardından bağlayıcıları (sorgular) ve bu bağlayıcıları web uygulamasında çağırmak için TypeScript kodunu uygulayacaksınız. Bu eğitimin sonunda uygulamanız, en yüksek puanlı ve en yeni filmleri doğrudan veritabanından dinamik olarak getirebilecek ve gösterebilecek.

Sahte film, oyuncu ve yorum verileri ekleme

  1. VSCode'da dataconnect/moviedata_insert.gql dosyasını açın. Firebase Data Connect uzantısındaki emülatörlerin çalıştığından emin olun.
  2. Dosyanın üst kısmında Run (local) [Çalıştır (yerel)] düğmesini görürsünüz. Sahte film verilerini veritabanınıza eklemek için bunu tıklayın.
    e424f75e63bf2e10.png
  3. Verilerin başarıyla eklendiğini onaylamak için Data Connect Execution terminalini kontrol edin.
    e0943d7704fb84ea.png

Bağlayıcıyı uygulama

  1. dataconnect/movie-connector/queries.gql adlı görüşmeyi açın. Yorumlarda temel bir ListMovies sorgusu bulabilirsiniz:
    query ListMovies @auth(level: PUBLIC) {
      movies {
        id
        title
        imageUrl
        releaseYear
        genre
        rating
        tags
        description
      }
    }
    
    Bu sorgu, tüm filmleri ve ayrıntılarını (örneğin, id, title, releaseYear) getirir. Ancak filmleri sıralamaz.
  2. Sıralama ve sınır seçenekleri eklemek için mevcut ListMovies sorgusunu aşağıdaki sorguyla değiştirin:
    # 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. Sorguyu yerel veritabanınızda yürütmek için Çalıştır (yerel) düğmesini tıklayın. Ayrıca, sorgu değişkenlerini çalıştırmadan önce yapılandırma bölmesine de girebilirsiniz.
    c4d947115bb11b16.png

Temel Çıkarımlar:

  • movies(): Veritabanından film verilerini getirmek için kullanılan GraphQL sorgu alanı.
  • orderByRating: Filmleri puana göre (artan/azalan) sıralamak için kullanılan parametre.
  • orderByReleaseYear: Filmleri yayınlanma yılına göre (artan/azalan) sıralamak için kullanılan parametre.
  • limit: Döndürülen film sayısını sınırlar.

Web uygulamasında sorguları entegre etme

Bu kod laboratuvarının bu bölümünde, önceki bölümde tanımlanan sorguları web uygulamanızda kullanacaksınız. Firebase Data Connect emülatörleri, .gql dosyalarındaki (özellikle schema.gql, queries.gql, mutations.gql) ve connector.yaml dosyasındaki bilgilere göre SDK'lar oluşturur. Bu SDK'lar uygulamanızda doğrudan çağrılabilir.

  1. MovieService (app/src/lib/MovieService.tsx) içinde, en üstteki içe aktarma ifadesinin yorumunu kaldırın:
    import { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect";
    
    İşlev listMovies, yanıt türü ListMoviesData ve enum OrderDirection, daha önce tanımladığınız şemaya ve sorgulara göre Firebase Data Connect emülatörleri tarafından oluşturulan SDK'lardır .
  2. handleGetTopMovies ve handleGetLatestMovies işlevlerini aşağıdaki kodla değiştirin:
    // 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;
      }
    };
    

Temel Çıkarımlar:

  • listMovies: Film listesini almak için listMovies sorgusunu çağıran otomatik olarak oluşturulmuş bir işlev. Puan veya yayın yılına göre sıralama ve sonuç sayısını sınırlama seçenekleri bulunur.
  • ListMoviesData: Uygulamanın ana sayfasında en iyi 10 ve en yeni filmleri göstermek için kullanılan sonuç türü.

İşleyiş şeklini görün

Sorgunun nasıl çalıştığını görmek için web uygulamanızı yeniden yükleyin. Ana sayfada artık filmlerin listesi dinamik olarak gösteriliyor ve veriler doğrudan yerel veritabanınızdan alınıyor. En çok beğenilen ve en yeni filmler, az önce ayarladığınız verileri yansıtacak şekilde sorunsuz bir şekilde gösterilir.

6. Film ve oyuncu ayrıntılarını görüntüleme

Bu bölümde, benzersiz kimliklerini kullanarak bir film veya oyuncu hakkında ayrıntılı bilgi almak için işlevselliği uygulayacaksınız. Bu işlem, yalnızca ilgili tablolardan veri getirmeyi değil, aynı zamanda film incelemeleri ve oyuncu filmografileri gibi kapsamlı ayrıntıları göstermek için ilgili tabloları birleştirmeyi de içerir.

ac7fefa7ff779231.png

Bağlayıcıları uygulama

  1. Projenizde dataconnect/movie-connector/queries.gql simgesini açın.
  2. Film ve oyuncu ayrıntılarını almak için aşağıdaki sorguları ekleyin:
    # 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. Değişikliklerinizi kaydedin ve sorguları inceleyin.

Temel Çıkarımlar:

  • movie()/actor(): Movies veya Actors tablosundan tek bir film ya da aktör getirmek için kullanılan GraphQL sorgu alanları.
  • _on_: Bu, yabancı anahtar ilişkisi olan ilişkili bir türdeki alanlara doğrudan erişilmesini sağlar. Örneğin, reviews_on_movie belirli bir filmle ilgili tüm yorumları getirir.
  • _via_: Birleştirme tablosu aracılığıyla çoktan çoğa ilişkilerde gezinmek için kullanılır. Örneğin, actors_via_MovieActor, MovieActor birleştirme tablosu aracılığıyla Actor türüne erişir ve where koşulu, oyuncuları rollerine göre (örneğin, "başrol" veya "yardımcı") filtreler.

Sorguyu sahte veriler girerek test etme

  1. Veri Bağlantısı yürütme bölmesinde, sorguyu aşağıdaki gibi sahte kimlikler girerek test edebilirsiniz:
    {"id": "550e8400-e29b-41d4-a716-446655440000"}
    
  2. GetMovieById için Run (local)'ı (Yerel Çalıştır) tıklayarak "Quantum Paradox" (yukarıdaki kimliğin ilişkili olduğu sahte film) hakkındaki ayrıntıları alın.

1b08961891e44da2.png

Web uygulamasında sorguları entegre etme

  1. MovieService (app/src/lib/MovieService.tsx) içinde aşağıdaki içe aktarma işlemlerinin yorum işaretini kaldırın:
    import { getMovieById, GetMovieByIdData } from "@movie/dataconnect";
    import { GetActorByIdData, getActorById } from "@movie/dataconnect";
    
  2. handleGetMovieById ve handleGetActorById işlevlerini aşağıdaki kodla değiştirin:
    // 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;
      }
    };
    

Temel Çıkarımlar:

  • getMovieById / getActorById: Bunlar, tanımladığınız sorguları çağıran ve belirli bir film veya oyuncu hakkında ayrıntılı bilgiler alan otomatik olarak oluşturulmuş işlevlerdir.
  • GetMovieByIdData / GetActorByIdData: Bunlar, uygulamada film ve oyuncu ayrıntılarını göstermek için kullanılan sonuç türleridir.

İşleyiş şeklini görün

Şimdi web uygulamanızın ana sayfasına gidin. Bir filmi tıkladığınızda, oyuncular ve yorumlar da dahil olmak üzere tüm ayrıntılarını (ilgili tablolardan alınan bilgiler) görebilirsiniz. Benzer şekilde, bir oyuncuyu tıkladığınızda yer aldığı filmler gösterilir.

7. Kullanıcı kimlik doğrulamasını işleme

Bu bölümde, Firebase Authentication'ı kullanarak kullanıcı oturum açma ve kapatma işlevlerini uygulayacaksınız. Ayrıca, Firebase DataConnect'te kullanıcı verilerini doğrudan almak veya eklemek için Firebase Authentication verilerini kullanacak ve uygulamanızda güvenli kullanıcı yönetimi sağlayacaksınız.

9890838045d5a00e.png

Bağlayıcıları uygulama

  1. dataconnect/movie-connector/ uygulamasında mutations.gql'ı tıklayın.
  2. Mevcut kimliği doğrulanmış kullanıcıyı oluşturmak veya güncellemek için aşağıdaki mutasyonu ekleyin:
    # Create or update the current authenticated user
    mutation UpsertUser($username: String!) @auth(level: USER) {
      user_upsert(
        data: {
          id_expr: "auth.uid"
          username: $username
        }
      )
    }
    

Temel Çıkarımlar:

  • id_expr: "auth.uid": Bu, kullanıcı veya uygulama tarafından değil, doğrudan Firebase Authentication tarafından sağlanan auth.uid özelliğini kullanır. Kullanıcı kimliğinin güvenli ve otomatik olarak işlenmesini sağlayarak ek bir güvenlik katmanı ekler.

Geçerli kullanıcıyı getirme

  1. dataconnect/movie-connector/ uygulamasında queries.gql'ı tıklayın.
  2. Mevcut kullanıcıyı getirmek için aşağıdaki sorguyu ekleyin:
    # 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
            }
          }
        }
      }
    }
    

Temel Çıkarımlar:

  • auth.uid: Bu, doğrudan Firebase Authentication'dan alınır ve kullanıcıya özel verilere güvenli erişim sağlanır.
  • _on_ alanları: Bu alanlar birleştirme tablolarını temsil eder:
    • reviews_on_user: Filmin id ve title dahil olmak üzere kullanıcıyla ilgili tüm yorumları getirir.
    • favorite_movies_on_user: genre, releaseYear, rating ve metadata gibi ayrıntılı bilgiler de dahil olmak üzere, kullanıcı tarafından favori olarak işaretlenen tüm filmleri alır.

Web uygulamasında sorguları entegre etme

  1. MovieService (app/src/lib/MovieService.tsx) içinde aşağıdaki içe aktarmaların yorumunu kaldırın:
    import { upsertUser } from "@movie/dataconnect";
    import { getCurrentUser, GetCurrentUserData } from "@movie/dataconnect";
    
  2. handleAuthStateChange ve handleGetCurrentUser işlevlerini aşağıdaki kodla değiştirin:
    // 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;
      }
    };
    

Temel Çıkarımlar:

  • handleAuthStateChange: Bu işlev, kimlik doğrulama durumu değişikliklerini dinler. Kullanıcı oturum açtığında kullanıcının verileri ayarlanır ve veritabanında kullanıcının bilgilerini oluşturmak veya güncellemek için upsertUser mutasyonu çağrılır.
  • handleGetCurrentUser: Kullanıcının yorumlarını ve favori filmlerini alan getCurrentUser sorgusunu kullanarak mevcut kullanıcının profilini getirir.

İşleyiş şeklini görün

Şimdi gezinme çubuğundaki "Google ile oturum açın" düğmesini tıklayın. Firebase Authentication emülatörünü kullanarak oturum açabilirsiniz. Oturum açtıktan sonra "Profilim"i tıklayın. Şu an için boş olsa da uygulamanızda kullanıcıya özel veri işleme için temel oluşturmuş oldunuz.

8. Kullanıcı etkileşimlerini uygulama

Bu codelab bölümünde, film yorumu uygulamasında kullanıcı etkileşimlerini uygulayacaksınız. Özellikle kullanıcıların favori filmlerini yönetmelerine ve yorum bırakmalarına ya da yorum silmelerine izin vereceksiniz.

b3d0ac1e181c9de9.png

Kullanıcıların filmleri favorilerine eklemesine izin verme

Bu bölümde, kullanıcıların filmleri favorilerine eklemesine olanak tanımak için veritabanını ayarlayacaksınız.

Bağlayıcıları uygulama

  1. dataconnect/movie-connector/ uygulamasında mutations.gql'ı tıklayın.
  2. Filmleri favorilere ekleme işlemini gerçekleştirmek için aşağıdaki mutasyonları ekleyin:
    # 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 })
    }
    
    

Temel Çıkarımlar:

  • userId_expr: "auth.uid": Doğrudan Firebase Authentication tarafından sağlanan auth.uid kullanır. Bu sayede yalnızca kimliği doğrulanmış kullanıcının verilerine erişilir veya bu veriler değiştirilir.

Bir filmin favorilere eklenip eklenmediğini kontrol etme

  1. dataconnect/movie-connector/ uygulamasında queries.gql'ı tıklayın.
  2. Bir filmin favorilere eklenip eklenmediğini kontrol etmek için aşağıdaki sorguyu ekleyin:
    query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
      favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
        movieId
      }
    }
    

Temel Çıkarımlar:

  • auth.uid: Firebase Authentication'ı kullanarak kullanıcıya özel verilere güvenli erişim sağlar.
  • favorite_movie: Belirli bir filmin mevcut kullanıcı tarafından favori olarak işaretlenip işaretlenmediğini görmek için favorite_movies birleştirme tablosunu kontrol eder.

Web uygulamasında sorguları entegre etme

  1. MovieService (app/src/lib/MovieService.tsx) içinde aşağıdaki içe aktarma işlemlerinin yorum işaretini kaldırın:
    import { addFavoritedMovie, deleteFavoritedMovie, getIfFavoritedMovie } from "@movie/dataconnect";
    
  2. handleAddFavoritedMovie, handleDeleteFavoritedMovie ve handleGetIfFavoritedMovie işlevlerini aşağıdaki kodla değiştirin:
    // 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;
      }
    };
    

Temel Çıkarımlar:

  • handleAddFavoritedMovie ve handleDeleteFavoritedMovie: Kullanıcının favorilerine güvenli bir şekilde film eklemek veya filmleri kaldırmak için mutasyonları kullanın.
  • handleGetIfFavoritedMovie: Bir filmin kullanıcı tarafından favori olarak işaretlenip işaretlenmediğini kontrol etmek için getIfFavoritedMovie sorgusunu kullanır.

İşleyiş şeklini görün

Artık film kartlarındaki ve film ayrıntıları sayfasındaki kalp simgesini tıklayarak filmleri favorilerinize ekleyebilir veya favorilerinizden kaldırabilirsiniz. Ayrıca, profil sayfanızda en sevdiğiniz filmleri görebilirsiniz.

Kullanıcıların yorum bırakmasına veya silmesine izin verme

Ardından, uygulamadaki kullanıcı yorumlarını yönetme bölümünü uygulayacaksınız.

Bağlayıcıları uygulama

mutations.gql (dataconnect/movie-connector/mutations.gql) içinde aşağıdaki mutasyonları ekleyin:

# 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 })
}

Temel Çıkarımlar:

  • userId_expr: "auth.uid": Yorumların, kimliği doğrulanmış kullanıcıyla ilişkilendirilmesini sağlar.
  • reviewDate_date: { today: true }: DataConnect'i kullanarak yorum için geçerli tarihi otomatik olarak oluşturur. Böylece manuel giriş yapmaya gerek kalmaz.

Web uygulamasında sorguları entegre etme

  1. MovieService (app/src/lib/MovieService.tsx) içinde aşağıdaki içe aktarma işlemlerinin yorum işaretini kaldırın:
    import { addReview, deleteReview } from "@movie/dataconnect";
    
  2. handleAddReview ve handleDeleteReview işlevlerini aşağıdaki kodla değiştirin:
    // 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;
      }
    };
    

Temel Çıkarımlar:

  • handleAddReview: Belirtilen film için yorum eklemek üzere addReview mutasyonunu çağırır ve yorumu kimliği doğrulanmış kullanıcıya güvenli bir şekilde bağlar.
  • handleDeleteReview: Kimliği doğrulanmış kullanıcının bir filmle ilgili yorumunu kaldırmak için deleteReview mutasyonunu kullanır.

İşleyiş şeklini görün

Kullanıcılar artık film ayrıntıları sayfasında filmlerle ilgili yorum bırakabilir. Kullanıcılar, profil sayfalarında yorumlarını görüntüleyip silebilir. Böylece, uygulamayla etkileşimleri üzerinde tam kontrol sahibi olurlar.

9. Gelişmiş filtreler ve kısmi metin eşleştirme

Bu bölümde, kullanıcıların filmleri çeşitli derecelere ve yayınlanma yıllarına göre aramasına, türlere ve etiketlere göre filtrelemesine, başlıklarda veya açıklamalarda kısmi metin eşlemesi yapmasına ve hatta daha hassas sonuçlar için birden fazla filtreyi birleştirmesine olanak tanıyan gelişmiş arama özelliklerini uygulayacaksınız.

ece70ee0ab964e28.png

Bağlayıcıları uygulama

  1. queries.gql dosyasını dataconnect/movie-connector/ uygulamasında açın.
  2. Çeşitli arama özelliklerini desteklemek için aşağıdaki sorguyu ekleyin:
    # 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
        }
      }
    }
    

Temel Çıkarımlar:

  • _and operatörü: Tek bir sorguda birden fazla koşulu birleştirerek aramanın releaseYear, rating ve genre gibi çeşitli alanlara göre filtrelenmesine olanak tanır.
  • contains operatörü: Alanlarda kısmi metin eşleşmelerini arar. Bu sorguda title, description, name veya reviewText içinde eşleşmeler aranır.
  • where ifadesi: Verilerin filtrelenme koşullarını belirtir. Her bölümde (filmler, aktörler, yorumlar) aramanın belirli ölçütlerini tanımlamak için bir where ifadesi kullanılır.

Web uygulamasında sorguları entegre etme

  1. MovieService (app/src/lib/MovieService.tsx) içinde aşağıdaki içe aktarma işlemlerinin yorum işaretini kaldırın:
    import { searchAll, SearchAllData } from "@movie/dataconnect";
    
  2. handleSearchAll işlevini aşağıdaki kodla değiştirin:
    // 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;
      }
    };
    

Temel Çıkarımlar:

  • handleSearchAll: Bu işlev, kullanıcının girişine göre arama yapmak için searchAll sorgusunu kullanır ve sonuçları yıl, puan, tür ve kısmi metin eşleşmeleri gibi parametrelere göre filtreler.

İşleyiş şeklini görün

Web uygulamasındaki gezinme çubuğundan "Gelişmiş Arama" sayfasına gidin. Artık çeşitli filtreler ve girişler kullanarak filmleri, aktörleri ve yorumları arayabilir, ayrıntılı ve kişiselleştirilmiş arama sonuçları elde edebilirsiniz.

10. İsteğe bağlı: Cloud'a dağıtma (faturalandırma gerekir)

Yerel geliştirme yinelemesini tamamladığınıza göre artık şemanızı, verilerinizi ve sorgularınızı sunucuya dağıtabilirsiniz. Bu işlem, Firebase Data Connect VS Code uzantısı veya Firebase CLI kullanılarak yapılabilir.

Firebase fiyatlandırma planınızı yükseltme

Firebase Data Connect'i PostgreSQL İçin Cloud SQL ile entegre etmek istiyorsanız Firebase projenizin kullandıkça öde (Blaze) fiyatlandırma planında olması gerekir. Bu da projenin bir Cloud Faturalandırma Hesabı'na bağlı olduğu anlamına gelir.

Projenizi Blaze planına yükseltmek için şu adımları uygulayın:

  1. Firebase konsolunda planınızı yükseltmeyi seçin.
  2. Blaze planını seçin. Bir Cloud Faturalandırma hesabını projenize bağlamak için ekrandaki talimatları uygulayın.
    Bu yükseltme kapsamında bir Cloud Faturalandırma hesabı oluşturmanız gerekiyorsa yükseltmeyi tamamlamak için Firebase Console'daki yükseltme akışına geri dönmeniz gerekebilir.

Web uygulamanızı Firebase projenize bağlama

  1. Firebase konsolunu kullanarak web uygulamanızı Firebase projenize kaydedin:
    1. Projenizi açın ve Uygulama Ekle'yi tıklayın.
    2. Şimdilik SDK kurulumu ve yapılandırma kurulumunu göz ardı edin ancak oluşturulan firebaseConfig nesnesini kopyaladığınızdan emin olun.
    7030822793e4d75b.png
  2. app/src/lib/firebase.tsx içindeki mevcut firebaseConfig değerini, Firebase konsolundan kopyaladığınız yapılandırmayla değiştirin.
    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 uygulamasını oluşturun: VS Code'a geri dönün ve app klasöründe, web uygulamasını barındırma dağıtımı için oluşturmak üzere Vite'ı kullanın:
    cd app
    npm run build
    

Firebase projenizde Firebase Authentication'ı ayarlama

  1. Google ile oturum açma özelliğini kullanarak Firebase Authentication'ı ayarlayın.62af2f225e790ef6.png
  2. (İsteğe bağlı) Firebase konsolunu kullanarak Firebase Authentication için alanlara izin verin (örneğin, http://127.0.0.1).
    1. Kimlik doğrulama ayarlarında Yetkili Alanlar'a gidin.
    2. "Alan Ekle"yi tıklayın ve yerel alanınızı listeye ekleyin.

c255098f12549886.png

Firebase CLI ile dağıtma

  1. dataconnect/dataconnect.yaml bölümünde, örnek kimliğinizin, veritabanınızın ve hizmet kimliğinizin projenizle eşleştiğinden emin olun:
    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. Firebase CLI'nın projenizle birlikte ayarlandığından emin olun:
    npm i -g firebase-tools
    firebase login --reauth
    firebase use --add
    
  3. Dağıtmak için terminalinizde aşağıdaki komutu çalıştırın:
    firebase deploy --only dataconnect,hosting
    
  4. Şema değişikliklerinizi karşılaştırmak için bu komutu çalıştırın:
    firebase dataconnect:sql:diff
    
  5. Değişiklikler kabul edilebilir durumdaysa bunları şu şekilde uygulayın:
    firebase dataconnect:sql:migrate
    

PostgreSQL için Cloud SQL örneğiniz, son dağıtılan şema ve verilerle güncellenir. Durumu Firebase konsolunda izleyebilirsiniz.

Artık uygulamanızı your-project.web.app/ adresinde canlı olarak görebilirsiniz. Ayrıca, yerel emülatörlerde yaptığınız gibi Firebase Data Connect panelinde Çalıştır (Üretim)'ı tıklayarak üretim ortamına veri ekleyebilirsiniz.

11. İsteğe bağlı: Firebase Data Connect ile vektör arama (faturalandırma gerekir)

Bu bölümde, Firebase Data Connect'i kullanarak film inceleme uygulamanızda vektör arama özelliğini etkinleştireceksiniz. Bu özellik, içerik tabanlı aramalara (ör. vektör gömmelerini kullanarak benzer açıklamalara sahip filmleri bulma) olanak tanır.

Bu adım için Google Cloud'a dağıtım yapmak üzere bu codelab'in son adımını tamamlamış olmanız gerekir.

4b5aca5a447d2feb.png

Şemayı, bir alan için yerleştirmeleri içerecek şekilde güncelleme

dataconnect/schema/schema.gql içinde, Movie tablosuna descriptionEmbedding alanını ekleyin:

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
}

Temel Çıkarımlar:

  • descriptionEmbedding: Vector @col(size:768): Bu alan, film açıklamalarının anlamsal yerleştirmelerini saklayarak uygulamanızda vektör tabanlı içerik araması yapmanızı sağlar.

Vertex AI'ı etkinleştirme

  1. Google Cloud'dan Vertex AI API'lerini ayarlamak için ön koşullar kılavuzunu inceleyin. Bu adım, yerleştirme oluşturma ve Vector Search işlevini desteklemek için gereklidir.
  2. Firebase Data Connect VS Code uzantısını kullanarak "Üretime dağıt"ı tıklayarak pgvector ve vektör arama özelliklerini etkinleştirmek için şemanızı yeniden dağıtın.

Veritabanını yerleştirmelerle doldurma

  1. VS Code'da dataconnect klasörünü açın.
  2. optional_vector_embed.gql bölümünde Run(local)'ı (Yerel olarak çalıştır) tıklayarak veritabanınızı filmlerin yerleştirmeleriyle doldurun.

b858da780f6ec103.png

Vektör arama sorgusu ekleme

dataconnect/movie-connector/queries.gql içinde vektör aramaları yapmak için aşağıdaki sorguyu ekleyin:

# 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
  }
}

Temel Çıkarımlar:

  • compare_embed: Karşılaştırma için yerleştirme modelini (textembedding-gecko@003) ve giriş metnini ($query) belirtir.
  • method: Öklid uzaklığını temsil eden benzerlik yöntemini (L2) belirtir.
  • within: Arama, 2 veya daha az L2 mesafesine sahip filmlerle sınırlandırılır ve yakın içerik eşleşmelerine odaklanılır.
  • limit: Döndürülen sonuç sayısını 5 ile sınırlar.

Uygulamanızda vektör arama işlevini uygulama

Şema ve sorgu ayarlandığına göre vektör arama işlevini uygulamanızın hizmet katmanına entegre edin. Bu adım, web uygulamanızdan arama sorgusunu çağırmanıza olanak tanır.

  1. app/src/lib/ MovieService.ts sürümünde, SDK'lardan aşağıdaki içe aktarmaların yorum işaretini kaldırın. Bu, diğer tüm sorgular gibi çalışır.
    import {
      searchMovieDescriptionUsingL2similarity,
      SearchMovieDescriptionUsingL2similarityData,
    } from "@movie/dataconnect";
    
  2. Vektör tabanlı aramayı uygulamaya entegre etmek için aşağıdaki işlevi ekleyin:
    // 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;
      }
    };
    

Temel Çıkarımlar:

  • searchMoviesByDescription: Bu işlev, vektör tabanlı içerik araması yapmak için giriş metnini ileterek searchMovieDescriptionUsingL2similarity sorgusunu çağırır.

İşleyiş şeklini görün

Gezinme çubuğunda "Vector Search" (Vektör Arama) bölümüne gidin ve "romantik ve modern" gibi ifadeler yazın. Aradığınız içeriğe uygun filmlerin listesini görürsünüz. Alternatif olarak, herhangi bir filmin ayrıntılar sayfasına gidip sayfanın alt kısmındaki benzer filmler bölümüne göz atabilirsiniz.

7b71f1c75633c1be.png

12. Sonuç

Tebrikler, web uygulamasını kullanabilirsiniz. Kendi film verilerinizle denemeler yapmak istiyorsanız endişelenmeyin. _insert.gql dosyalarını taklit ederek Firebase Data Connect uzantısını kullanarak kendi verilerinizi ekleyin veya bunları VS Code'daki Data Connect yürütme bölmesi üzerinden ekleyin.

Daha fazla bilgi