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 menampilkan cara Firebase Data Connect menyederhanakan proses build aplikasi yang didukung SQL. Fitur ini mencakup:
- Autentikasi: Terapkan autentikasi kustom untuk kueri dan mutasi aplikasi Anda, sehingga memastikan hanya pengguna yang berwenang 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: Mengambil, memperbarui, dan mengelola 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.
Yang Akan Anda Pelajari
- Siapkan 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.
- Deploy skema dan kelola database secara efisien.
Yang Anda Butuhkan
- 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 Blaze
Menyiapkan Lingkungan Pengembangan Anda
Bagian ini akan memandu Anda menyiapkan lingkungan untuk mulai mem-build aplikasi ulasan film menggunakan Firebase Data Connect.
Langkah 1: Meng-clone Repositori Project
Mulailah dengan meng-clone repositori project dan menginstal 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.
Langkah 2: Buka Project di Visual Studio Code
Buka folder codelab-dataconnect-web
yang di-clone menggunakan Visual Studio Code. Di sinilah Anda akan menentukan skema, menulis kueri, dan menguji fungsionalitas aplikasi.
Langkah 3: Instal Ekstensi Visual Studio Firebase Data Connect
Untuk menggunakan fitur Data Connect, instal Ekstensi Visual Studio Firebase Data Connect. Atau: Instal dari Visual Studio Code Marketplace atau telusuri dalam VS Code.
- Atau: Instal dari Visual Studio Code Marketplace atau telusuri dalam VS Code.
Langkah 4: Buat Project Firebase
Buka Firebase Console untuk membuat project Firebase baru jika Anda belum memilikinya. Kemudian, di ekstensi VSCode Firebase Data Connect:
- Klik tombol Login.
- Klik Connect a Firebase Project lalu pilih project yang Anda buat di Firebase Console.
Langkah 5: Mulai emulator Firebase
Di ekstensi VSCode Firebase Data Connect, klik Start Emulators, dan pastikan emulator sedang berjalan di terminal.
2. Meninjau codebase awal
Di bagian ini, Anda akan menjelajahi area utama codebase awal aplikasi. Meskipun aplikasi tidak memiliki beberapa fungsi, sebaiknya pahami keseluruhan strukturnya.
Struktur folder dan file
Berikut ringkasan singkat tentang struktur folder dan file aplikasi:
{i>dataconnect/<i}
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 Anda.connector/mutations.gql
: Mutasi yang diperlukan di aplikasi Anda.connector/connector.yaml:
File konfigurasi untuk pembuatan SDK
aplikasi/src/
Berisi logika aplikasi dan interaksi dengan Firebase Data Connect.
firebase.ts
: Konfigurasi untuk terhubung ke aplikasi Firebase di konsol.lib/dataconnect-sdk/
: Folder ini berisi SDK yang dihasilkan. Anda dapat mengedit lokasi pembuatan SDK di file connector/connector.yaml dan SDK akan otomatis dibuat setiap kali Anda menentukan kueri atau mutasi.
3. 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 ditetapkan menggunakan Firebase Data Connect dan perintah skema GraphQL. Setelah ada, aplikasi Anda akan siap menangani semuanya mulai dari mencari film dengan peringkat teratas dan memfilter berdasarkan genre hingga membiarkan 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. Dengan jenis FavoriteMovie
, pengguna dapat memfavoritkan film, sehingga aplikasi dapat menampilkan daftar favorit yang dipersonalisasi dan menyoroti pilihan populer.
Tabel Film
Jenis Film menentukan struktur utama untuk entitas film, termasuk kolom seperti judul, genre, tahun rilis, 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()")
.
Tabel MovieMetadata
Jenis MovieMetadata menetapkan hubungan one-to-one dengan jenis Movie. 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.
Tabel Pelaku
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, membentuk hubungan many-to-many.
Tabel Pelaku Film
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 "mendukung").
Tabel Pengguna
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
}
Tabel FavoriteMovie
Jenis FavoriteMovie
adalah tabel gabungan yang menangani hubungan many-to-many antara pengguna dan film atau aktor 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 Film, secara implisit membuat MovieId dengan kunci asing: UUID!.
- user: Mereferensikan jenis pengguna, secara implisit membuat userId kunci asing: UUID!.
Tabel Ulasan
Jenis Ulasan mewakili entitas ulasan dan menautkan jenis Pengguna dan Film 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 diulas.
- reviewDate: Otomatis ditetapkan ke waktu saat ulasan dibuat menggunakan
@default(expr: "request.time")
.
Kolom dan Setelan 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 Film dan Ulasan akan otomatis diisi dengan UUID saat data baru dibuat.
Setelah skema ditentukan, aplikasi film Anda memiliki fondasi yang kuat untuk struktur data dan hubungannya.
4. Mengambil Film Terpopuler 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 Simulasi
- 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 {i>database<i} Anda.
- Periksa terminal Data Connect Execution untuk mengonfirmasi bahwa data berhasil ditambahkan.
Mengimplementasikan Konektor
- Buka
dataconnect/movie-connector/queries.gql
. Anda akan menemukan kueriListMovies
dasar di komentar:
query ListMovies @auth(level: PUBLIC) {
movies {
id
title
imageUrl
releaseYear
genre
rating
tags
description
}
}
Kueri ini mengambil semua film dan detailnya (mis., id, title, releaseYear). Namun, tindakan ini tidak mengurutkan film.
- Ganti kueri
ListMovies
dengan kueri di bawah ini 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 (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 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 (schema.gql, queries.gql, mutations.gql) dan connector.yaml. SDK ini dapat langsung dipanggil dalam aplikasi Anda.
- Di
MovieService
(app/src/lib/MovieService.tsx
), hapus komentar pernyataan impor di bagian atas:
import { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect";
Fungsi listMovies
, jenis respons ListMoviesData
, dan enum OrderDirection
adalah SDK yang dihasilkan oleh emulator Firebase Data Connect berdasarkan skema dan kueri yang telah Anda tetapkan 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 kueri listMovies 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 film terbaru di halaman beranda.
Lihat Penerapannya
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.
5. Menampilkan Detail Film dan Aktor
Di bagian ini, Anda akan mengimplementasikan 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.
Mengimplementasikan 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 tabel Film atau Aktor._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 many-to-many melalui tabel gabungan. Misalnya,actors_via_MovieActor
mengakses jenis Aktor melalui tabel penggabungan MovieActor, dan kondisiwhere
memfilter aktor berdasarkan perannya (mis., "utama" atau "mendukung").
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 dihasilkan 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 dalam 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.
6. 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.
Mengimplementasikan 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 Penting:
id_expr: "auth.uid"
: Metode ini menggunakanauth.uid
, yang disediakan langsung oleh Firebase Authentication, bukan oleh pengguna atau aplikasi, yang menambahkan lapisan keamanan ekstra dengan memastikan ID pengguna ditangani secara aman dan otomatis.
Selanjutnya, buka queries.gql
di dataconnect/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._on_
Kolom: Kolom ini mewakili tabel gabungan:reviews_on_user
: Mengambil semua ulasan yang terkait dengan pengguna, termasuk ID dan judul film.favorite_movies_on_user
: Mengambil semua film yang ditandai sebagai favorit oleh pengguna, termasuk informasi mendetail seperti genre, tahun rilis, rating, dan metadata.
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, fungsi ini 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 Penerapannya
Sekarang, klik tombol "Login dengan Google" di menu navigasi. Anda dapat login menggunakan emulator Firebase Auth. Setelah login, klik "Profil Saya". Untuk saat ini, tabel ini akan kosong, tetapi Anda telah menyiapkan dasar untuk penanganan data khusus pengguna di aplikasi.
7. Mengimplementasikan Interaksi Pengguna
Di bagian ini, Anda akan menerapkan interaksi pengguna di aplikasi ulasan film, yang memungkinkan pengguna mengelola film favorit mereka dan memberikan atau menghapus ulasan.
Mengimplementasikan 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, memastikan bahwa hanya data pengguna terautentikasi yang diakses atau diubah.
- Selanjutnya, 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 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 Penerapannya
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.
Menerapkan Ulasan Pengguna
Berikutnya, Anda akan menerapkan bagian untuk mengelola ulasan pengguna di aplikasi.
Mengimplementasikan 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 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, menautkannya dengan aman ke pengguna yang diautentikasi.handleDeleteReview
: Menggunakan mutasideleteReview
untuk menghapus ulasan film oleh pengguna terautentikasi.
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.
8. 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.
Mengimplementasikan 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 Penerapannya
Buka "Penelusuran Lanjutan" dari {i>navigationbar<i} di aplikasi web. Kini Anda dapat menelusuri film, aktor, dan ulasan menggunakan berbagai filter dan input, sehingga Anda mendapatkan hasil penelusuran yang disesuaikan dan mendetail.
9. Opsional: Men-deploy ke Cloud (Penagihan Wajib)
Setelah Anda menyelesaikan iterasi pengembangan lokal, kini saatnya untuk men-deploy skema, data, dan kueri Anda ke server. Hal ini dapat dilakukan menggunakan ekstensi Firebase Data Connect VS Code atau Firebase CLI.
Menambahkan Aplikasi Web di Firebase Console
- Buat Aplikasi Web di Firebase Console dan catat ID Aplikasi Anda
- Siapkan aplikasi web di Firebase Console dengan mengklik "Add App". Untuk saat ini, Anda dapat mengabaikan penyiapan SDK dan penyiapan konfigurasi dengan aman, tetapi perhatikan objek
firebaseConfig
yang dihasilkan. - Ganti
firebaseConfig
diapp/src/lib/firebase.tsx
:
const firebaseConfig = { apiKey: "API_KEY", authDomain: "PROJECT_ID.firebaseapp.com", projectId: "PROJECT_ID", storageBucket: "PROJECT_ID.appspot.com", messagingSenderId: "SENDER_ID", appId: "APP_ID" };
- Mem-build Aplikasi Web: Di folder
app
, gunakan Vite untuk mem-build aplikasi web untuk deployment hosting:
cd app npm run build
Menyiapkan Firebase Authentication di Console
- Menyiapkan Firebase Auth dengan Login dengan Google
- (Opsional) Izinkan domain untuk (Firebase Auth) [https://firebase.google.com/docs/auth/web/hosting] di konsol project Anda (mis.,
http://127.0.0.1
):
- Di setelan Auth, pilih project Anda dan buka (Authorized Domains) [https://firebase.google.com/docs/auth/web/hosting]. 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 Anda, 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.
10. Opsional: Penelusuran Vektor dengan Firebase Data Connect
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 yang mirip menggunakan embedding vektor.
Memperbarui Skema untuk Menyertakan Embedding untuk Kolom
- Di
dataconnect/schema/schema.gql
, tambahkan kolomdescriptionEmbedding
ke tabelMovie
:
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 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 dengan 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 VSCode Firebase Data Connect.
Mengisi Database dengan Penyematan
- Buka folder
dataconnect
di VSCode dan klik Run(local) dioptional_vector_embed.gql
untuk mengisi database 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 kemiripan (L2
), yang mewakili jarak Euclidean.within
: Membatasi penelusuran pada film dengan jarak L2 2 atau kurang, dengan fokus pada kecocokan konten yang dekat.limit
: Membatasi jumlah hasil yang ditampilkan, yaitu 5.
Mengimplementasikan Fungsi Penelusuran Vektor di Aplikasi
- Di
app/src/lib/MovieService.ts
, hapus tanda komentar pada impor berikut:
Mengimplementasikan Vector Search Function dalam aplikasi
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 Penerapannya
Navigasikan ke "Penelusuran Vektor" di menu navigasi dan 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.
11. Kesimpulan
Selamat, Anda seharusnya dapat menggunakan aplikasi web. Jika Anda ingin menggunakan data film Anda sendiri, jangan khawatir, masukkan data Anda sendiri menggunakan ekstensi FDC dengan meniru file _insert.gql, atau tambahkan melalui panel Eksekusi Data Connect.