1. Sebelum memulai
Dalam codelab ini, Anda akan mengintegrasikan Firebase Data Connect dengan database Cloud SQL untuk mem-build aplikasi web ulasan film. Aplikasi yang telah selesai menunjukkan cara Firebase Data Connect menyederhanakan proses pembuatan aplikasi yang didukung SQL. Fitur ini mencakup:
- Autentikasi: Terapkan autentikasi kustom untuk kueri dan mutasi aplikasi Anda, sehingga memastikan hanya pengguna yang diotorisasi yang dapat berinteraksi dengan data Anda.
- Skema GraphQL: Buat dan kelola struktur data Anda menggunakan skema GraphQL yang fleksibel dan disesuaikan dengan kebutuhan aplikasi web ulasan film.
- Kueri dan mutasi SQL: Ambil, perbarui, dan kelola data di Cloud SQL menggunakan kueri dan mutasi yang didukung oleh GraphQL.
- Penelusuran lanjutan dengan pencocokan string sebagian: Gunakan filter dan opsi penelusuran untuk menemukan film berdasarkan kolom seperti judul, deskripsi, atau tag.
- (Opsional) Integrasi penelusuran vektor: Tambahkan fungsi penelusuran konten menggunakan penelusuran vektor Firebase Data Connect untuk memberikan pengalaman pengguna yang kaya berdasarkan input dan preferensi.
Prasyarat
Anda memerlukan pemahaman dasar tentang JavaScript.
Hal yang akan Anda pelajari
- Menyiapkan Firebase Data Connect dengan emulator lokal.
- Buat desain skema data menggunakan Data Connect dan GraphQL.
- Menulis dan menguji berbagai kueri dan mutasi untuk aplikasi ulasan film.
- Pelajari cara Firebase Data Connect membuat dan menggunakan SDK di aplikasi.
- Men-deploy skema dan mengelola database secara efisien.
Hal yang akan Anda perlukan
- Git
- Visual Studio Code
- Instal Node.js menggunakan nvm-windows (Windows) atau nvm (macOS/Linux)
- Jika Anda belum melakukannya, buat project Firebase di Firebase console
- (Opsional) Untuk penelusuran vektor, upgrade project Anda ke paket harga Blaze bayar sesuai penggunaan
2. Menyiapkan lingkungan pengembangan
Tahap codelab ini akan memandu Anda menyiapkan lingkungan untuk mulai mem-build aplikasi ulasan film menggunakan Firebase Data Connect.
- Clone repositori project dan instal dependensi yang diperlukan:
git clone https://github.com/firebaseextended/codelab-dataconnect-web cd codelab-dataconnect-web cd ./app && npm i npm run dev
- Setelah menjalankan perintah ini, buka http://localhost:5173 di browser Anda untuk melihat aplikasi web yang berjalan secara lokal. Ini berfungsi sebagai frontend Anda untuk mem-build aplikasi ulasan film dan berinteraksi dengan fiturnya.
- Buka folder
codelab-dataconnect-web
yang di-clone menggunakan Visual Studio Code. Di sinilah Anda akan menentukan skema, menulis kueri, dan menguji fungsi aplikasi. - Untuk menggunakan fitur Data Connect, instal Ekstensi Visual Studio Firebase Data Connect.
Atau, Anda dapat menginstal ekstensi dari Visual Studio Code Marketplace atau menelusurinya dalam VS Code. - Buka atau buat project Firebase baru di Firebase console.
- Hubungkan project Firebase Anda ke ekstensi VSCode Firebase Data Connect. Di ekstensi, lakukan hal berikut:
- Klik tombol Login.
- Klik Connect a Firebase Project dan pilih project Firebase Anda.
- Mulai emulator Firebase menggunakan ekstensi VS Code Firebase Data Connect:
Klik Start Emulators, lalu pastikan emulator berjalan di terminal.
3. Meninjau codebase awal
Di bagian ini, Anda akan mempelajari area utama codebase awal aplikasi. Meskipun aplikasi ini tidak memiliki beberapa fungsi, sebaiknya pahami struktur keseluruhannya.
Struktur folder dan file
Subbagian berikut memberikan ringkasan struktur folder dan file aplikasi.
Direktori dataconnect/
Berisi konfigurasi Firebase Data Connect, konektor (yang menentukan kueri dan mutasi), dan file skema.
schema/schema.gql
: Menentukan skema GraphQLconnector/queries.gql
: Kueri yang diperlukan di aplikasi Andaconnector/mutations.gql
: Mutasi yang diperlukan di aplikasi Andaconnector/connector.yaml
: File konfigurasi untuk pembuatan SDK
Direktori app/src/
Berisi logika aplikasi dan interaksi dengan Firebase Data Connect.
firebase.ts
: Konfigurasi untuk terhubung ke Aplikasi Firebase di project Firebase Anda.lib/dataconnect-sdk/
: Berisi SDK yang dihasilkan. Anda dapat mengedit lokasi pembuatan SDK di fileconnector/connector.yaml
dan SDK akan otomatis dibuat setiap kali Anda menentukan kueri atau mutasi.
4. Menentukan skema untuk ulasan film
Di bagian ini, Anda akan menentukan struktur dan hubungan antara entitas utama dalam aplikasi film dalam skema. Entity seperti Movie
, User
, Actor
, dan Review
dipetakan ke tabel database, dengan hubungan yang dibuat menggunakan Firebase Data Connect dan perintah skema GraphQL. Setelah diterapkan, aplikasi Anda akan siap menangani segala hal, mulai dari menelusuri film dengan rating teratas dan memfilter menurut genre hingga memungkinkan pengguna memberikan ulasan, menandai favorit, menjelajahi film serupa, atau menemukan film yang direkomendasikan berdasarkan input teks melalui penelusuran vektor.
Entitas dan hubungan inti
Jenis Movie
menyimpan detail utama seperti judul, genre, dan tag, yang digunakan aplikasi untuk penelusuran dan profil film. Jenis User
melacak interaksi pengguna, seperti ulasan dan favorit. Reviews
menghubungkan pengguna ke film, sehingga aplikasi dapat menampilkan rating dan masukan yang dibuat pengguna.
Hubungan antara film, aktor, dan pengguna membuat aplikasi lebih dinamis. Tabel join MovieActor
membantu menampilkan detail pemeran dan filmografi aktor. Jenis FavoriteMovie
memungkinkan pengguna memfavoritkan film, sehingga aplikasi dapat menampilkan daftar favorit yang dipersonalisasi dan menyoroti pilihan populer.
Menyiapkan tabel Movie
Jenis Movie
menentukan struktur utama untuk entity film, termasuk kolom seperti title
, genre
, releaseYear
, dan rating
.
Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql
Anda:
type Movie
@table {
id: UUID! @default(expr: "uuidV4()")
title: String!
imageUrl: String!
releaseYear: Int
genre: String
rating: Float
description: String
tags: [String]
}
Poin-Poin Penting:
- id: UUID unik untuk setiap film, yang dibuat menggunakan
@default(expr: "uuidV4()")
.
Menyiapkan tabel MovieMetadata
Jenis MovieMetadata
menetapkan hubungan satu-ke-satu dengan jenis Movie
. Data ini mencakup data tambahan seperti sutradara film.
Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql
Anda:
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
}
Poin-Poin Penting:
- Film! @ref: Mereferensikan jenis
Movie
, yang menetapkan hubungan kunci asing.
Menyiapkan tabel Actor
Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql
Anda:
type Actor @table {
id: UUID!
imageUrl: String!
name: String! @col(name: "name", dataType: "varchar(30)")
}
Jenis Actor
mewakili aktor dalam database film, dengan setiap aktor dapat menjadi bagian dari beberapa film, sehingga membentuk hubungan many-to-many.
Menyiapkan tabel MovieActor
Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql
Anda:
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"
}
Poin-Poin Penting:
- movie: Mereferensikan jenis Movie, secara implisit menghasilkan kunci asing movieId: UUID!.
- actor: Mereferensikan jenis Pelaku, secara implisit menghasilkan kunci asing actorId: UUID!.
- role: Menentukan peran aktor dalam film (misalnya, "utama" atau "pendukung").
Menyiapkan tabel User
Jenis User
menentukan entity pengguna yang berinteraksi dengan film dengan memberikan ulasan atau memfavoritkan film.
Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql
Anda:
type User
@table {
id: String! @col(name: "auth_uid")
username: String! @col(dataType: "varchar(50)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
Menyiapkan tabel FavoriteMovie
Jenis FavoriteMovie
adalah tabel join yang menangani hubungan many-to-many antara pengguna dan film favorit mereka. Setiap tabel menautkan User
ke Movie
.
Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql
Anda:
type FavoriteMovie
@table(name: "FavoriteMovies", singular: "favorite_movie", plural: "favorite_movies", key: ["user", "movie"]) {
# @ref is implicit
user: User!
movie: Movie!
}
Poin-Poin Penting:
- movie: Mereferensikan jenis Movie, secara implisit menghasilkan kunci asing
movieId: UUID!
. - user: Mereferensikan jenis pengguna, secara implisit menghasilkan kunci asing
userId: UUID!
.
Menyiapkan tabel Review
Jenis Review
mewakili entity ulasan dan menautkan jenis User
dan Movie
dalam hubungan many-to-many (satu pengguna dapat memberikan banyak ulasan, dan setiap film dapat memiliki banyak ulasan).
Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql
Anda:
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")
}
Poin-Poin Penting:
- user: Mereferensikan pengguna yang memberikan ulasan.
- movie: Mereferensikan film yang sedang ditinjau.
- reviewDate: Otomatis ditetapkan ke waktu saat ulasan dibuat menggunakan
@default(expr: "request.time")
.
Kolom dan default yang dibuat otomatis
Skema menggunakan ekspresi seperti @default(expr: "uuidV4()")
untuk membuat ID dan stempel waktu unik secara otomatis. Misalnya, kolom id
dalam jenis Movie
dan Review
akan otomatis diisi dengan UUID saat data baru dibuat.
Setelah skema ditentukan, aplikasi film Anda memiliki dasar yang kuat untuk struktur dan hubungan datanya.
5. Mengambil film teratas dan terbaru
Di bagian ini, Anda akan menyisipkan data film tiruan ke emulator lokal, lalu menerapkan konektor (kueri) dan kode TypeScript untuk memanggil konektor ini di aplikasi web. Pada akhirnya, aplikasi Anda akan dapat mengambil dan menampilkan film dengan rating tertinggi dan terbaru secara dinamis langsung dari database.
Menyisipkan data film, aktor, dan ulasan tiruan
- Di VSCode, buka
dataconnect/moviedata_insert.gql
. Pastikan emulator di ekstensi Firebase Data Connect sedang berjalan. - Anda akan melihat tombol Run (local) di bagian atas file. Klik ini untuk menyisipkan data film tiruan ke dalam database Anda.
- Periksa terminal Data Connect Execution untuk mengonfirmasi bahwa data berhasil ditambahkan.
Menerapkan konektor
- Buka
dataconnect/movie-connector/queries.gql
. Anda akan menemukan kueriListMovies
dasar di komentar: Kueri ini mengambil semua film dan detailnya (misalnya,query ListMovies @auth(level: PUBLIC) { movies { id title imageUrl releaseYear genre rating tags description } }
id
,title
,releaseYear
). Namun, kueri ini tidak mengurutkan film. - Ganti kueri
ListMovies
yang ada dengan kueri berikut untuk menambahkan opsi pengurutan dan batas:# 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 } }
- Klik tombol Run (local) untuk menjalankan kueri terhadap database lokal Anda. Anda juga dapat memasukkan variabel kueri di panel konfigurasi sebelum menjalankannya.
Poin-Poin Penting:
movies()
: Kolom kueri GraphQL untuk mengambil data film dari database.orderByRating
: Parameter untuk mengurutkan film menurut rating (menurut urutan menaik/menurun).orderByReleaseYear
: Parameter untuk mengurutkan film menurut tahun rilis (menurut urutan menaik/menurun).limit
: Membatasi jumlah film yang ditampilkan.
Mengintegrasikan kueri di aplikasi web
Di bagian codelab ini, Anda akan menggunakan kueri yang ditentukan di bagian sebelumnya di aplikasi web Anda. Emulator Firebase Data Connect menghasilkan SDK berdasarkan informasi dalam file .gql
(khususnya, schema.gql
, queries.gql
, mutations.gql
) dan file connector.yaml
. SDK ini dapat langsung dipanggil di aplikasi Anda.
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus komentar pernyataan impor di bagian atas: Fungsiimport { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect";
listMovies
, jenis responsListMoviesData
, dan enumOrderDirection
adalah semua SDK yang dihasilkan oleh emulator Firebase Data Connect berdasarkan skema dan kueri yang telah Anda tentukan sebelumnya . - Ganti fungsi
handleGetTopMovies
danhandleGetLatestMovies
dengan kode berikut:// 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; } };
Poin-Poin Penting:
listMovies
: Fungsi yang dibuat otomatis yang memanggil kuerilistMovies
untuk mengambil daftar film. Halaman ini mencakup opsi untuk mengurutkan menurut rating atau tahun rilis dan membatasi jumlah hasil.ListMoviesData
: Jenis hasil yang digunakan untuk menampilkan 10 film teratas dan terbaru di halaman beranda aplikasi.
Lihat cara kerjanya
Muat ulang aplikasi web Anda untuk melihat cara kerja kueri. Halaman beranda kini menampilkan daftar film secara dinamis, mengambil data langsung dari database lokal Anda. Anda akan melihat film dengan rating tertinggi dan terbaru muncul dengan lancar, yang mencerminkan data yang baru saja Anda siapkan.
6. Menampilkan detail film dan aktor
Di bagian ini, Anda akan menerapkan fungsi untuk mengambil informasi mendetail tentang film atau aktor menggunakan ID uniknya. Hal ini tidak hanya melibatkan pengambilan data dari tabel masing-masing, tetapi juga menggabungkan tabel terkait untuk menampilkan detail yang komprehensif, seperti ulasan film dan filmografi aktor.
Menerapkan konektor
- Buka
dataconnect/movie-connector/queries.gql
di project Anda. - Tambahkan kueri berikut untuk mengambil detail film dan aktor:
# 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 } } }
- Simpan perubahan dan tinjau kueri.
Poin-Poin Penting:
movie()
/actor()
: Kolom kueri GraphQL untuk mengambil satu film atau aktor dari tabelMovies
atauActors
._on_
: Hal ini memungkinkan akses langsung ke kolom dari jenis terkait yang memiliki hubungan kunci asing. Misalnya,reviews_on_movie
mengambil semua ulasan yang terkait dengan film tertentu._via_
: Digunakan untuk menavigasi hubungan banyak-ke-banyak melalui tabel join. Misalnya,actors_via_MovieActor
mengakses jenisActor
melalui tabel joinMovieActor
, dan kondisiwhere
memfilter aktor berdasarkan perannya (misalnya, "utama" atau "pendukung").
Menguji kueri dengan memasukkan data tiruan
- Di panel eksekusi Data Connect, Anda dapat menguji kueri dengan memasukkan ID tiruan, seperti:
{"id": "550e8400-e29b-41d4-a716-446655440000"}
- Klik Run (local) untuk
GetMovieById
guna mengambil detail tentang "Quantum Paradox" (film tiruan yang terkait dengan ID di atas).
Mengintegrasikan kueri di aplikasi web
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus tanda komentar impor berikut:import { getMovieById, GetMovieByIdData } from "@movie/dataconnect"; import { GetActorByIdData, getActorById } from "@movie/dataconnect";
- Ganti fungsi
handleGetMovieById
danhandleGetActorById
dengan kode berikut:// 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; } };
Poin-Poin Penting:
getMovieById
/getActorById
: Ini adalah fungsi yang dibuat otomatis yang memanggil kueri yang Anda tentukan, mengambil informasi mendetail untuk film atau aktor tertentu.GetMovieByIdData
/GetActorByIdData
: Ini adalah jenis hasil, yang digunakan untuk menampilkan detail film dan aktor di aplikasi.
Lihat cara kerjanya
Sekarang, buka halaman beranda aplikasi web Anda. Klik film, dan Anda akan dapat melihat semua detailnya, termasuk aktor dan ulasan—informasi yang diambil dari tabel terkait. Demikian pula, mengklik aktor akan menampilkan film yang dibintanginya.
7. Menangani autentikasi pengguna
Di bagian ini, Anda akan menerapkan fungsi login dan logout pengguna menggunakan Firebase Authentication. Anda juga akan menggunakan data Firebase Authentication untuk mengambil atau memperbarui data pengguna secara langsung di Firebase DataConnect, sehingga memastikan pengelolaan pengguna yang aman dalam aplikasi Anda.
Menerapkan konektor
- Buka
mutations.gql
didataconnect/movie-connector/
. - Tambahkan mutasi berikut untuk membuat atau memperbarui pengguna terautentikasi saat ini:
# Create or update the current authenticated user mutation UpsertUser($username: String!) @auth(level: USER) { user_upsert( data: { id_expr: "auth.uid" username: $username } ) }
Poin-Poin Penting:
id_expr: "auth.uid"
: Ini menggunakanauth.uid
, yang disediakan langsung oleh Firebase Authentication, bukan oleh pengguna atau aplikasi, sehingga menambahkan lapisan keamanan tambahan dengan memastikan ID pengguna ditangani dengan aman dan otomatis.
Mengambil pengguna saat ini
- Buka
queries.gql
didataconnect/movie-connector/
. - Tambahkan kueri berikut untuk mengambil pengguna saat ini:
# 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 } } } } }
Poin-Poin Penting:
auth.uid
: Data ini diambil langsung dari Firebase Authentication, sehingga memastikan akses yang aman ke data khusus pengguna.- Kolom
_on_
: Kolom ini mewakili tabel join:reviews_on_user
: Mengambil semua ulasan yang terkait dengan pengguna, termasukid
dantitle
film.favorite_movies_on_user
: Mengambil semua film yang ditandai sebagai favorit oleh pengguna, termasuk informasi mendetail sepertigenre
,releaseYear
,rating
, danmetadata
.
Mengintegrasikan kueri di aplikasi web
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus tanda komentar pada impor berikut:import { upsertUser } from "@movie/dataconnect"; import { getCurrentUser, GetCurrentUserData } from "@movie/dataconnect";
- Ganti fungsi
handleAuthStateChange
danhandleGetCurrentUser
dengan kode berikut:// 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; } };
Poin-Poin Penting:
handleAuthStateChange
: Fungsi ini memproses perubahan status autentikasi. Saat pengguna login, tindakan ini akan menetapkan data pengguna dan memanggil mutasiupsertUser
untuk membuat atau memperbarui informasi pengguna di database.handleGetCurrentUser
: Mengambil profil pengguna saat ini menggunakan kuerigetCurrentUser
, yang mengambil ulasan dan film favorit pengguna.
Lihat cara kerjanya
Sekarang, klik tombol "Login dengan Google" di menu navigasi. Anda dapat login menggunakan emulator Firebase Authentication. Setelah login, klik "Profil Saya". Untuk saat ini, tabel ini akan kosong, tetapi Anda telah menyiapkan dasar untuk penanganan data khusus pengguna di aplikasi.
8. Mengimplementasikan interaksi pengguna
Di bagian codelab ini, Anda akan menerapkan interaksi pengguna di aplikasi ulasan film, khususnya memungkinkan pengguna mengelola film favorit mereka dan memberikan atau menghapus ulasan.
Memungkinkan pengguna memfavoritkan film
Di bagian ini, Anda akan menyiapkan database untuk memungkinkan pengguna memfavoritkan film.
Menerapkan konektor
- Buka
mutations.gql
didataconnect/movie-connector/
. - Tambahkan mutasi berikut untuk menangani film favorit:
# 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 }) }
Poin-Poin Penting:
userId_expr: "auth.uid"
: Menggunakanauth.uid
, yang disediakan langsung oleh Firebase Authentication, untuk memastikan bahwa hanya data pengguna yang diautentikasi yang diakses atau diubah.
Memeriksa apakah film difavoritkan
- Buka
queries.gql
didataconnect/movie-connector/
. - Tambahkan kueri berikut untuk memeriksa apakah film difavoritkan:
query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) { favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) { movieId } }
Poin-Poin Penting:
auth.uid
: Memastikan akses yang aman ke data khusus pengguna menggunakan Firebase Authentication.favorite_movie
: Memeriksa tabel joinfavorite_movies
untuk melihat apakah film tertentu ditandai sebagai favorit oleh pengguna saat ini.
Mengintegrasikan kueri di aplikasi web
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus tanda komentar impor berikut:import { addFavoritedMovie, deleteFavoritedMovie, getIfFavoritedMovie } from "@movie/dataconnect";
- Ganti fungsi
handleAddFavoritedMovie
,handleDeleteFavoritedMovie
, danhandleGetIfFavoritedMovie
dengan kode berikut:// 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; } };
Poin-Poin Penting:
handleAddFavoritedMovie
danhandleDeleteFavoritedMovie
: Gunakan mutasi untuk menambahkan atau menghapus film dari favorit pengguna dengan aman.handleGetIfFavoritedMovie
: Menggunakan kuerigetIfFavoritedMovie
untuk memeriksa apakah film ditandai sebagai favorit oleh pengguna.
Lihat cara kerjanya
Sekarang, Anda dapat memfavoritkan atau membatalkan favorit film dengan mengklik ikon hati di kartu film dan halaman detail film. Selain itu, Anda dapat melihat film favorit di halaman profil.
Mengizinkan pengguna memberikan atau menghapus ulasan
Selanjutnya, Anda akan menerapkan bagian untuk mengelola ulasan pengguna di aplikasi.
Menerapkan konektor
Di mutations.gql
(dataconnect/movie-connector/mutations.gql
): Tambahkan mutasi berikut:
# 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 })
}
Poin-Poin Penting:
userId_expr: "auth.uid"
: Memastikan bahwa ulasan dikaitkan dengan pengguna yang diautentikasi.reviewDate_date: { today: true }
: Otomatis membuat tanggal saat ini untuk peninjauan menggunakan DataConnect, sehingga Anda tidak perlu memasukkan data secara manual.
Mengintegrasikan kueri di aplikasi web
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus tanda komentar impor berikut:import { addReview, deleteReview } from "@movie/dataconnect";
- Ganti fungsi
handleAddReview
danhandleDeleteReview
dengan kode berikut:// 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; } };
Poin-Poin Penting:
handleAddReview
: Memanggil mutasiaddReview
untuk menambahkan ulasan film yang ditentukan, dengan menautkan ulasan tersebut ke pengguna yang diautentikasi dengan aman.handleDeleteReview
: Menggunakan mutasideleteReview
untuk menghapus ulasan film oleh pengguna yang diautentikasi.
Lihat cara kerjanya
Pengguna kini dapat memberikan ulasan untuk film di halaman detail film. Mereka juga dapat melihat dan menghapus ulasan mereka di halaman profil, sehingga mereka memiliki kontrol penuh atas interaksi mereka dengan aplikasi.
9. Filter lanjutan dan pencocokan teks sebagian
Di bagian ini, Anda akan menerapkan kemampuan penelusuran lanjutan, yang memungkinkan pengguna menelusuri film berdasarkan rentang rating dan tahun rilis, memfilter menurut genre dan tag, melakukan pencocokan teks sebagian dalam judul atau deskripsi, dan bahkan menggabungkan beberapa filter untuk hasil yang lebih akurat.
Menerapkan konektor
- Buka
queries.gql
didataconnect/movie-connector/
. - Tambahkan kueri berikut untuk mendukung berbagai kemampuan penelusuran:
# 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 } } }
Poin-Poin Penting:
- Operator
_and
: Menggabungkan beberapa kondisi dalam satu kueri, sehingga penelusuran dapat difilter menurut beberapa kolom sepertireleaseYear
,rating
, dangenre
. - Operator
contains
: Menelusuri kecocokan teks sebagian dalam kolom. Dalam kueri ini, kueri akan mencari kecocokan dalamtitle
,description
,name
, ataureviewText
. - Klausa
where
: Menentukan kondisi untuk memfilter data. Setiap bagian (film, aktor, ulasan) menggunakan klausawhere
untuk menentukan kriteria tertentu untuk penelusuran.
Mengintegrasikan kueri di aplikasi web
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus tanda komentar impor berikut:import { searchAll, SearchAllData } from "@movie/dataconnect";
- Ganti fungsi
handleSearchAll
dengan kode berikut:// 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; } };
Poin-Poin Penting:
handleSearchAll
: Fungsi ini menggunakan kuerisearchAll
untuk melakukan penelusuran berdasarkan input pengguna, memfilter hasil berdasarkan parameter seperti tahun, rating, genre, dan kecocokan teks sebagian.
Lihat cara kerjanya
Buka halaman "Penelusuran Lanjutan" dari menu navigasi di aplikasi web. Sekarang Anda dapat menelusuri film, aktor, dan ulasan menggunakan berbagai filter dan input, sehingga mendapatkan hasil penelusuran yang mendetail dan disesuaikan.
10. Opsional: Men-deploy ke Cloud (penagihan diperlukan)
Setelah Anda menyelesaikan iterasi pengembangan lokal, sekarang saatnya men-deploy skema, data, dan kueri ke server. Hal ini dapat dilakukan menggunakan ekstensi VS Code Firebase Data Connect atau Firebase CLI.
Mengupgrade paket harga Firebase
Untuk mengintegrasikan Firebase Data Connect dengan Cloud SQL untuk PostgreSQL, project Firebase Anda harus menggunakan paket harga bayar sesuai penggunaan (Blaze), yang berarti project tersebut ditautkan ke akun Penagihan Cloud.
- Akun Penagihan Cloud memerlukan metode pembayaran, seperti kartu kredit.
- Jika Anda baru menggunakan Firebase dan Google Cloud, periksa apakah Anda memenuhi syarat untuk mendapatkan kredit sebesar$300 dan akun Penagihan Cloud Uji Coba Gratis.
- Jika Anda melakukan codelab ini sebagai bagian dari acara, tanyakan kepada penyelenggara apakah ada kredit Cloud yang tersedia.
Untuk mengupgrade project Anda ke paket Blaze, ikuti langkah-langkah berikut:
- Di Firebase console, pilih upgrade your plan.
- Pilih paket Blaze. Ikuti petunjuk di layar untuk menautkan akun Penagihan Cloud ke project Anda.
Jika perlu membuat akun Penagihan Cloud sebagai bagian dari upgrade ini, Anda mungkin perlu kembali ke alur upgrade di Firebase console untuk menyelesaikan upgrade.
Menghubungkan aplikasi web ke project Firebase
- Daftarkan aplikasi web Anda di project Firebase menggunakan Firebase console:
- Buka project Anda, lalu klik Tambahkan Aplikasi.
- Abaikan penyiapan SDK dan penyiapan konfigurasi untuk saat ini, tetapi pastikan untuk menyalin objek
firebaseConfig
yang dihasilkan.
- Ganti
firebaseConfig
yang ada diapp/src/lib/firebase.tsx
dengan konfigurasi yang baru saja Anda salin dari Firebase console.const firebaseConfig = { apiKey: "API_KEY", authDomain: "PROJECT_ID.firebaseapp.com", projectId: "PROJECT_ID", storageBucket: "PROJECT_ID.firebasestorage.app", messagingSenderId: "SENDER_ID", appId: "APP_ID" };
- Mem-build aplikasi web: Kembali ke VS Code, di folder
app
, gunakan Vite untuk mem-build aplikasi web untuk deployment hosting:cd app npm run build
Menyiapkan Firebase Authentication di project Firebase Anda
- Siapkan Firebase Authentication dengan Login dengan Google.
- (Opsional) Izinkan domain untuk Firebase Authentication menggunakan Firebase console (misalnya,
http://127.0.0.1
).- Di setelan Authentication, buka Authorized Domains.
- Klik "Tambahkan Domain" dan sertakan domain lokal Anda dalam daftar.
Men-deploy dengan Firebase CLI
- Di
dataconnect/dataconnect.yaml
, pastikan ID instance, database, dan layanan Anda cocok dengan project Anda: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"]
- Pastikan Anda telah menyiapkan Firebase CLI dengan project Anda:
npm i -g firebase-tools firebase login --reauth firebase use --add
- Di terminal, jalankan perintah berikut untuk men-deploy:
firebase deploy --only dataconnect,hosting
- Jalankan perintah ini untuk membandingkan perubahan skema Anda:
firebase dataconnect:sql:diff
- Jika perubahan tersebut dapat diterima, terapkan dengan:
firebase dataconnect:sql:migrate
Instance Cloud SQL untuk PostgreSQL Anda akan diperbarui dengan skema dan data akhir yang di-deploy. Anda dapat memantau statusnya di Firebase console.
Sekarang Anda dapat melihat aplikasi yang aktif di your-project.web.app/
. Selain itu, Anda dapat mengklik Run (Production) di panel Firebase Data Connect, seperti yang Anda lakukan dengan emulator lokal, untuk menambahkan data ke lingkungan produksi.
11. Opsional: Penelusuran vektor dengan Firebase Data Connect (penagihan diperlukan)
Di bagian ini, Anda akan mengaktifkan penelusuran vektor di aplikasi ulasan film menggunakan Firebase Data Connect. Fitur ini memungkinkan penelusuran berbasis konten, seperti menemukan film dengan deskripsi serupa menggunakan penyematan vektor.
Langkah ini mengharuskan Anda menyelesaikan langkah terakhir codelab ini untuk men-deploy ke Google Cloud.
Memperbarui skema untuk menyertakan penyematan untuk kolom
Di dataconnect/schema/schema.gql
, tambahkan kolom descriptionEmbedding
ke tabel Movie
:
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
}
Poin-Poin Penting:
descriptionEmbedding: Vector @col(size:768)
: Kolom ini menyimpan penyematan semantik deskripsi film, yang memungkinkan penelusuran konten berbasis vektor di aplikasi Anda.
Mengaktifkan Vertex AI
- Ikuti panduan prasyarat untuk menyiapkan Vertex AI API dari Google Cloud. Langkah ini penting untuk mendukung fungsi pembuatan penyematan dan penelusuran vektor.
- Deploy ulang skema Anda untuk mengaktifkan
pgvector
dan penelusuran vektor dengan mengklik "Deploy to Production" menggunakan ekstensi VS Code Firebase Data Connect.
Mengisi database dengan penyematan
- Buka folder
dataconnect
di VS Code. - Klik Run(local) di
optional_vector_embed.gql
untuk mengisi database Anda dengan penyematan untuk film.
Menambahkan kueri penelusuran vektor
Di dataconnect/movie-connector/queries.gql
, tambahkan kueri berikut untuk melakukan penelusuran vektor:
# 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
}
}
Poin-Poin Penting:
compare_embed
: Menentukan model penyematan (textembedding-gecko@003
) dan teks input ($query
) untuk perbandingan.method
: Menentukan metode kesamaan (L2
), yang mewakili jarak Euclidean.within
: Membatasi penelusuran ke film dengan jarak L2 2 atau kurang, yang berfokus pada kecocokan konten yang dekat.limit
: Membatasi jumlah hasil yang ditampilkan menjadi 5.
Mengimplementasikan fungsi penelusuran vektor di aplikasi Anda
Setelah skema dan kueri disiapkan, integrasikan penelusuran vektor ke dalam lapisan layanan aplikasi Anda. Langkah ini memungkinkan Anda memanggil kueri penelusuran dari aplikasi web.
- Di
app/src/lib/
MovieService.ts
, hapus tanda komentar impor berikut dari SDK, ini akan berfungsi seperti kueri lainnya.import { searchMovieDescriptionUsingL2similarity, SearchMovieDescriptionUsingL2similarityData, } from "@movie/dataconnect";
- Tambahkan fungsi berikut untuk mengintegrasikan penelusuran berbasis vektor ke dalam aplikasi:
// 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; } };
Poin-Poin Penting:
searchMoviesByDescription
: Fungsi ini memanggil kuerisearchMovieDescriptionUsingL2similarity
, yang meneruskan teks input untuk melakukan penelusuran konten berbasis vektor.
Lihat cara kerjanya
Buka bagian "Vector Search" di menu navigasi samping, lalu ketik frasa seperti "romantis dan modern". Anda akan melihat daftar film yang cocok dengan konten yang Anda telusuri, atau, buka halaman detail film dari film mana pun, dan lihat bagian film serupa di bagian bawah halaman.
12. Kesimpulan
Selamat, Anda seharusnya dapat menggunakan aplikasi web. Jika Anda ingin menggunakan data film Anda sendiri, jangan khawatir, masukkan data Anda sendiri menggunakan ekstensi Firebase Data Connect dengan meniru file _insert.gql
, atau tambahkan melalui panel eksekusi Data Connect di VS Code.