1. Sebelum memulai
Dalam codelab ini, Anda akan mengintegrasikan Firebase Data Connect dengan database Cloud SQL untuk membangun aplikasi web ulasan film. Aplikasi yang telah selesai menunjukkan cara Firebase Data Connect menyederhanakan proses membangun aplikasi yang didukung SQL. Paket ini mencakup fitur berikut:
- Autentikasi: Terapkan autentikasi kustom untuk kueri dan mutasi aplikasi Anda, sehingga hanya pengguna yang berwenang yang dapat berinteraksi dengan data Anda.
- Skema GraphQL: Buat dan kelola struktur data Anda menggunakan skema GraphQL fleksibel yang 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 parsial: 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
- Siapkan Firebase Data Connect dengan emulator lokal.
- Merancang skema data menggunakan Data Connect dan GraphQL.
- Tulis dan uji berbagai kueri dan mutasi untuk aplikasi ulasan film.
- Pelajari cara Firebase Data Connect membuat dan menggunakan SDK di aplikasi.
- Deploy skema dan kelola 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 membuat 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 front-end Anda untuk membangun 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 mencarinya di 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 Hubungkan Project Firebase dan pilih project Firebase Anda.
- Mulai emulator Firebase menggunakan ekstensi VS Code Firebase Data Connect:
Klik Start Emulators, lalu konfirmasi bahwa emulator berjalan di terminal.
3. Meninjau codebase awal
Di bagian ini, Anda akan mempelajari area utama codebase awal aplikasi. Meskipun aplikasi tidak memiliki beberapa fungsi, memahami struktur keseluruhannya akan sangat membantu.
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
: Perubahan 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 dibuat secara otomatis 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. Entitas seperti Movie
, User
, Actor
, dan Review
dipetakan ke tabel database, dengan hubungan yang dibuat menggunakan Firebase Data Connect dan direktif skema GraphQL. Setelah diterapkan, aplikasi Anda akan siap menangani semuanya, mulai dari menelusuri film dengan rating tertinggi 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 menjadi lebih dinamis. Tabel gabungan MovieActor
membantu menampilkan detail pemeran dan filmografi aktor. Jenis FavoriteMovie
memungkinkan pengguna menandai film sebagai favorit, sehingga aplikasi dapat menampilkan daftar favorit yang dipersonalisasi dan menandai pilihan populer.
Menyiapkan tabel Movie
Jenis Movie
menentukan struktur utama untuk entity film, termasuk kolom seperti title
, genre
, releaseYear
, dan rating
.
Salin dan tempelkan cuplikan kode ke dalam 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 tempelkan cuplikan kode ke dalam 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: Merujuk ke jenis
Movie
, yang menetapkan hubungan kunci asing.
Menyiapkan tabel Actor
Salin dan tempelkan cuplikan kode ke dalam file dataconnect/schema/schema.gql
Anda:
type Actor @table {
id: UUID!
imageUrl: String!
name: String! @col(name: "name", dataType: "varchar(30)")
}
Jenis Actor
merepresentasikan aktor dalam database film, di mana setiap aktor dapat menjadi bagian dari beberapa film, sehingga membentuk hubungan banyak-ke-banyak.
Menyiapkan tabel MovieActor
Salin dan tempelkan cuplikan kode ke dalam 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: Merujuk ke jenis Movie, secara implisit menghasilkan kunci asing movieId: UUID!.
- actor: Merujuk ke jenis Actor, 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 menandai film sebagai favorit.
Salin dan tempelkan cuplikan kode ke dalam file dataconnect/schema/schema.gql
Anda:
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
}
Menyiapkan tabel FavoriteMovie
Jenis FavoriteMovie
adalah tabel gabungan yang menangani hubungan many-to-many antara pengguna dan film favorit mereka. Setiap tabel menautkan User
ke Movie
.
Salin dan tempelkan cuplikan kode ke dalam 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: Merujuk ke jenis Film, secara implisit menghasilkan kunci asing
movieId: UUID!
. - pengguna: Merujuk pada jenis pengguna, secara implisit menghasilkan kunci asing
userId: UUID!
.
Menyiapkan tabel Review
Jenis Review
merepresentasikan 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 tempelkan cuplikan kode ke dalam 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:
- pengguna: Merujuk pada pengguna yang memberikan ulasan.
- film: Merujuk pada film yang diulas.
- reviewDate: Otomatis ditetapkan ke waktu saat ulasan dibuat menggunakan
@default(expr: "request.time")
.
Kolom dan default yang dibuat otomatis
Skema ini 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 record 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 memasukkan 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 terbaru dan berperingkat teratas secara dinamis langsung dari database.
Masukkan data tiruan film, aktor, dan ulasan
- 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 memasukkan data film tiruan ke dalam database Anda.
- Periksa terminal Eksekusi Koneksi Data 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 menjalankan.
Poin-Poin Penting:
movies()
: Kolom kueri GraphQL untuk mengambil data film dari database.orderByRating
: Parameter untuk mengurutkan film berdasarkan rating (naik/turun).orderByReleaseYear
: Parameter untuk mengurutkan film berdasarkan tahun rilis (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 dipanggil langsung 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
semuanya adalah SDK yang dibuat 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 secara otomatis yang memanggil kuerilistMovies
untuk mengambil daftar film. Opsi ini mencakup pengurutan menurut rating atau tahun rilis dan pembatasan jumlah hasil.ListMoviesData
: Jenis hasil yang digunakan untuk menampilkan 10 film teratas dan terbaru di halaman beranda aplikasi.
Lihat penerapannya
Muat ulang aplikasi web Anda untuk melihat cara kerja kueri. Halaman beranda kini menampilkan daftar film secara dinamis, dengan mengambil data langsung dari database lokal Anda. Anda akan melihat film terbaru dan berperingkat teratas 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 masing-masing tabel, 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 Anda 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 gabungan. Misalnya,actors_via_MovieActor
mengakses jenisActor
melalui tabel gabunganMovieActor
, dan kondisiwhere
memfilter aktor berdasarkan perannya (misalnya, "utama" atau "pendukung").
Uji 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 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 secara 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 penerapannya
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 meng-upsert 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 ekstra dengan memastikan ID pengguna ditangani secara 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
: ID ini diambil langsung dari Firebase Authentication, sehingga memastikan akses yang aman ke data khusus pengguna.- Kolom
_on_
: Kolom ini mewakili tabel gabungan: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 komentar 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, data pengguna akan ditetapkan dan mutasiupsertUser
akan dipanggil untuk membuat atau memperbarui informasi pengguna di database.handleGetCurrentUser
: Mengambil profil pengguna saat ini menggunakan kuerigetCurrentUser
, yang mengambil ulasan pengguna dan film favorit.
Lihat penerapannya
Sekarang, klik tombol "Login dengan Google" di navbar. Anda dapat login menggunakan emulator Firebase Authentication. Setelah login, klik "Profil Saya". Untuk saat ini, kolom tersebut akan kosong, tetapi Anda telah menyiapkan dasar untuk penanganan data khusus pengguna di aplikasi Anda.
8. Menerapkan 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.
Mengizinkan pengguna menandai film sebagai favorit
Di bagian ini, Anda akan menyiapkan database agar pengguna dapat menandai film sebagai favorit.
Menerapkan konektor
- Buka
mutations.gql
didataconnect/movie-connector/
. - Tambahkan mutasi berikut untuk menangani pemberian tanda suka pada film:
# 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, sehingga hanya data pengguna yang diautentikasi yang diakses atau diubah.
Memeriksa apakah film ditandai sebagai favorit
- Buka
queries.gql
didataconnect/movie-connector/
. - Tambahkan kueri berikut untuk memeriksa apakah film ditandai sebagai favorit:
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 gabunganfavorite_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 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 penerapannya
Sekarang, Anda dapat menandai atau membatalkan tanda film favorit dengan mengklik ikon hati di kartu film dan halaman detail film. Selain itu, Anda dapat melihat film favorit di halaman profil Anda.
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 ulasan menggunakan DataConnect, sehingga tidak perlu memasukkan secara manual.
Mengintegrasikan kueri di aplikasi web
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus 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 untuk film yang ditentukan, dengan menautkannya secara aman ke pengguna yang diautentikasi.handleDeleteReview
: Menggunakan mutasideleteReview
untuk menghapus ulasan film oleh pengguna yang diautentikasi.
Lihat penerapannya
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 presisi.
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, kecocokan dicari dalamtitle
,description
,name
, ataureviewText
. - Klausul
where
: Menentukan kondisi untuk memfilter data. Setiap bagian (film, aktor, ulasan) menggunakan klausawhere
untuk menentukan kriteria spesifik untuk penelusuran.
Mengintegrasikan kueri di aplikasi web
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus 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 menurut parameter seperti tahun, rating, genre, dan kecocokan teks parsial.
Lihat penerapannya
Buka halaman "Penelusuran Lanjutan" dari navbar di aplikasi web. Sekarang Anda dapat menelusuri film, aktor, dan ulasan menggunakan berbagai filter dan input, serta mendapatkan hasil penelusuran yang mendetail dan disesuaikan.
10. Opsional: 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 Firebase Data Connect VS Code 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.
Hubungkan aplikasi web Anda ke project Firebase
- Daftarkan aplikasi web Anda di project Firebase menggunakan Firebase console:
- Buka project Anda, lalu klik Tambahkan Aplikasi.
- Abaikan penyiapan dan konfigurasi SDK 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" };
- Bangun aplikasi web: Kembali di VS Code, di folder
app
, gunakan Vite untuk membangun 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 ID 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 dapat diterima, terapkan dengan:
firebase dataconnect:sql:migrate
Instance Cloud SQL untuk PostgreSQL Anda akan diperbarui dengan skema dan data yang di-deploy terakhir. Anda dapat memantau status di Firebase console.
Sekarang Anda dapat melihat aplikasi Anda secara live 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 embedding 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 sematan semantik deskripsi film, sehingga 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 embedding 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 embedding
- 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 embedding (textembedding-gecko@003
) dan teks input ($query
) untuk perbandingan.method
: Menentukan metode kemiripan (L2
), yang merepresentasikan jarak Euclidean.within
: Membatasi penelusuran ke film dengan jarak L2 2 atau kurang, dengan berfokus pada kecocokan konten yang dekat.limit
: Membatasi jumlah hasil yang ditampilkan menjadi 5.
Menerapkan 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 komentar impor berikut dari SDK, yang 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
, meneruskan teks input untuk melakukan penelusuran konten berbasis vektor.
Lihat penerapannya
Buka bagian "Vector Search" di navbar dan ketik frasa seperti "romantic and modern". Anda akan melihat daftar film yang cocok dengan konten yang Anda cari, atau, buka halaman detail film apa pun, dan lihat bagian film serupa di bagian bawah halaman.
12. Kesimpulan
Selamat, Anda 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.