۱. قبل از شروع

در این آزمایشگاه کد، شما Firebase Data Connect را با یک پایگاه داده Cloud SQL ادغام خواهید کرد تا یک برنامه وب نقد فیلم بسازید. برنامه تکمیل شده نشان میدهد که چگونه Firebase Data Connect فرآیند ساخت برنامههای مبتنی بر SQL را ساده میکند. این برنامه شامل این ویژگیها است:
- احراز هویت: احراز هویت سفارشی را برای کوئریها و جهشهای برنامه خود پیادهسازی کنید، و اطمینان حاصل کنید که فقط کاربران مجاز میتوانند با دادههای شما تعامل داشته باشند.
- طرح GraphQL: با استفاده از یک طرح GraphQL انعطافپذیر که متناسب با نیازهای یک برنامه وب نقد فیلم طراحی شده است، ساختارهای داده خود را ایجاد و مدیریت کنید.
- کوئریها و جهشهای SQL: بازیابی، بهروزرسانی و مدیریت دادهها در Cloud SQL با استفاده از کوئریها و جهشهای ارائه شده توسط GraphQL.
- جستجوی پیشرفته با تطبیق جزئی رشته: از فیلترها و گزینههای جستجو برای یافتن فیلمها بر اساس فیلدهایی مانند عنوان، توضیحات یا برچسبها استفاده کنید.
- (اختیاری) ادغام جستجوی برداری: قابلیت جستجوی محتوا را با استفاده از جستجوی برداری Firebase Data Connect اضافه کنید تا یک تجربه کاربری غنی بر اساس ورودی و تنظیمات برگزیده ارائه دهید.
پیشنیازها
شما به درک اولیهای از جاوا اسکریپت نیاز خواهید داشت.
آنچه یاد خواهید گرفت
- Firebase Data Connect را با شبیهسازهای محلی راهاندازی کنید.
- طراحی یک طرح داده با استفاده از Data Connect و GraphQL
- کوئریها و جهشهای مختلفی را برای یک اپلیکیشن نقد فیلم بنویسید و آزمایش کنید.
- بیاموزید که چگونه Firebase Data Connect SDK را در برنامه تولید و استفاده میکند.
- طرحواره خود را مستقر کنید و پایگاه داده را به طور کارآمد مدیریت کنید.
آنچه نیاز دارید
- گیت
- ویژوال استودیو کد
- نصب Node.js با استفاده از nvm-windows (ویندوز) یا nvm (مک/لینوکس)
- اگر قبلاً این کار را نکردهاید، یک پروژه Firebase در کنسول Firebase ایجاد کنید
- (اختیاری) برای جستجوی برداری، پروژه خود را به طرح قیمتگذاری پرداخت در محل Blaze ارتقا دهید
۲. محیط توسعه خود را تنظیم کنید
این مرحله از codelab شما را در راهاندازی محیط برای شروع ساخت برنامه نقد فیلم با استفاده از Firebase Data Connect راهنمایی میکند.
- مخزن پروژه را کلون کنید و وابستگیهای مورد نیاز را نصب کنید:
git clone https://github.com/firebaseextended/codelab-dataconnect-web cd codelab-dataconnect-web cd ./app && npm i npm run dev
- پس از اجرای این دستورات، آدرس http://localhost:5173 را در مرورگر خود باز کنید تا برنامه وب را که به صورت محلی اجرا میشود، مشاهده کنید. این به عنوان رابط کاربری شما برای ساخت برنامه نقد فیلم و تعامل با ویژگیهای آن عمل میکند.

- پوشهی شبیهسازیشدهی
codelab-dataconnect-webرا با استفاده از Visual Studio Code باز کنید . اینجا جایی است که شما طرحوارهی خود را تعریف میکنید، کوئریها را مینویسید و عملکرد برنامه را آزمایش میکنید. - برای استفاده از ویژگیهای Data Connect، افزونهی Firebase Data Connect Visual Studio را نصب کنید.
همچنین میتوانید افزونه را از Visual Studio Code Marketplace نصب کنید یا آن را در VS Code جستجو کنید.
- یک پروژه Firebase جدید را در کنسول Firebase باز یا ایجاد کنید.
- پروژه فایربیس خود را به افزونه Firebase Data Connect VSCode متصل کنید. در این افزونه، موارد زیر را انجام دهید:
- روی دکمه ورود کلیک کنید.
- روی «اتصال یک پروژه Firebase» کلیک کنید و پروژه Firebase خود را انتخاب کنید.

- شبیهسازهای Firebase را با استفاده از افزونه Firebase Data Connect VS Code اجرا کنید:
روی شروع شبیهسازها کلیک کنید و سپس تأیید کنید که شبیهسازها در ترمینال اجرا میشوند.
۳. کدبیس اولیه را بررسی کنید
در این بخش، بخشهای کلیدی کد اولیهی برنامه را بررسی خواهید کرد. اگرچه برنامه برخی از قابلیتها را ندارد، اما درک ساختار کلی آن مفید خواهد بود.
ساختار پوشه و فایل
زیربخشهای زیر، نمای کلی از ساختار پوشهها و فایلهای برنامه را ارائه میدهند.
دایرکتوری dataconnect/
شامل پیکربندیهای Firebase Data Connect، کانکتورها (که کوئریها و جهشها را تعریف میکنند) و فایلهای طرحواره است.
-
schema/schema.gql: طرحواره GraphQL را تعریف میکند. -
connector/queries.gql: کوئریهای مورد نیاز در برنامه شما -
connector/mutations.gql: جهشهای مورد نیاز در برنامه شما -
connector/connector.yaml: فایل پیکربندی برای تولید SDK
دایرکتوری app/src/
شامل منطق برنامه و تعامل با Firebase Data Connect است.
-
firebase.ts: پیکربندی برای اتصال به یک برنامه Firebase در پروژه Firebase شما. -
lib/dataconnect-sdk/: شامل SDK تولید شده است. میتوانید محل تولید SDK را در فایلconnector/connector.yamlویرایش کنید و SDKها هر زمان که یک کوئری یا جهش تعریف کنید، به طور خودکار تولید میشوند.
۴. یک طرحواره برای نقد فیلم تعریف کنید
در این بخش، ساختار و روابط بین موجودیتهای کلیدی در برنامه فیلم را در یک طرحواره تعریف خواهید کرد. موجودیتهایی مانند Movie ، User ، Actor و Review به جداول پایگاه داده نگاشت میشوند و روابط آنها با استفاده از دستورالعملهای طرحواره Firebase Data Connect و GraphQL برقرار میشود. پس از راهاندازی، برنامه شما آماده خواهد بود تا همه چیز را از جستجوی فیلمهای برتر و فیلتر کردن بر اساس ژانر گرفته تا اجازه دادن به کاربران برای گذاشتن نقد، علامتگذاری موارد دلخواه، بررسی فیلمهای مشابه یا یافتن فیلمهای پیشنهادی بر اساس ورودی متن از طریق جستجوی برداری، مدیریت کند.
موجودیتهای اصلی و روابط
نوع Movie (Movie type) جزئیات کلیدی مانند عنوان، ژانر و برچسبها را در خود جای داده است که برنامه برای جستجوها و پروفایلهای فیلم از آنها استفاده میکند. نوع User (User type) تعاملات کاربر، مانند نقدها و موارد دلخواه را پیگیری میکند. Reviews کاربران را به فیلمها متصل میکنند و به برنامه اجازه میدهند رتبهبندیها و بازخوردهای ایجاد شده توسط کاربر را نشان دهد.
روابط بین فیلمها، بازیگران و کاربران، برنامه را پویاتر میکند. جدول عضویت MovieActor به نمایش جزئیات بازیگران و فیلمشناسی بازیگران کمک میکند. نوع FavoriteMovie به کاربران امکان میدهد فیلمهای مورد علاقه خود را انتخاب کنند، بنابراین برنامه میتواند یک لیست دلخواه شخصیسازی شده را نشان دهد و انتخابهای محبوب را برجسته کند.
میز Movie را تنظیم کنید
نوع Movie ساختار اصلی یک موجودیت فیلم را تعریف میکند، از جمله فیلدهایی مانند title ، genre ، releaseYear و rating .
قطعه کد را کپی کرده و در فایل dataconnect/schema/schema.gql خود قرار دهید:
type Movie
@table {
id: UUID! @default(expr: "uuidV4()")
title: String!
imageUrl: String!
releaseYear: Int
genre: String
rating: Float
description: String
tags: [String]
}
نکات کلیدی:
- شناسه: یک UUID منحصر به فرد برای هر فیلم، که با استفاده از
@default(expr: "uuidV4()") تولید میشود.
جدول MovieMetadata را تنظیم کنید
نوع MovieMetadata یک رابطه یک به یک با نوع Movie برقرار میکند. این نوع شامل دادههای اضافی مانند کارگردان فیلم نیز میشود.
قطعه کد را کپی کرده و در فایل dataconnect/schema/schema.gql خود قرار دهید:
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
}
نکات کلیدی:
- Movie! @ref: به نوع
Movieاشاره میکند و یک رابطهی کلید خارجی برقرار میکند.
جدول Actor را تنظیم کنید
قطعه کد را کپی کرده و در فایل dataconnect/schema/schema.gql خود قرار دهید:
type Actor @table {
id: UUID!
imageUrl: String!
name: String! @col(name: "name", dataType: "varchar(30)")
}
نوع Actor نشان دهنده یک بازیگر در پایگاه داده فیلم است، که در آن هر بازیگر میتواند بخشی از چندین فیلم باشد و یک رابطه چند به چند تشکیل دهد.
جدول MovieActor را تنظیم کنید
قطعه کد را کپی کرده و در فایل dataconnect/schema/schema.gql خود قرار دهید:
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"
}
نکات کلیدی:
- movie: به نوع Movie اشاره میکند، به طور ضمنی یک کلید خارجی movieId: UUID! تولید میکند.
- actor: به نوع Actor اشاره میکند، به طور ضمنی یک کلید خارجی actorId: UUID! تولید میکند.
- نقش: نقش بازیگر را در فیلم تعریف میکند (مثلاً «اصلی» یا «مکمل»).
تنظیم جدول User
نوع User ، یک موجودیت کاربری را تعریف میکند که با گذاشتن نقد یا اضافه کردن فیلم به لیست علاقهمندیها، با فیلمها تعامل دارد.
قطعه کد را کپی کرده و در فایل dataconnect/schema/schema.gql خود قرار دهید:
type User
@table {
id: String! @col
username: String! @col(dataType: "varchar(50)")
# The following are generated from the @ref in the Review table
# reviews_on_user
# movies_via_Review
}
جدول FavoriteMovie تنظیم کنید
نوع FavoriteMovie یک جدول پیوند است که روابط چند به چند بین کاربران و فیلمهای مورد علاقهشان را مدیریت میکند. هر جدول یک User به یک Movie پیوند میدهد.
قطعه کد را کپی کرده و در فایل dataconnect/schema/schema.gql خود قرار دهید:
type FavoriteMovie
@table(name: "FavoriteMovies", singular: "favorite_movie", plural: "favorite_movies", key: ["user", "movie"]) {
# @ref is implicit
user: User!
movie: Movie!
}
نکات کلیدی:
- movie: به نوع Movie اشاره میکند، به طور ضمنی یک کلید خارجی
movieId: UUID!تولید میکند. - کاربر: به نوع کاربر اشاره میکند، به طور ضمنی یک کلید خارجی
userId: UUID!تولید میکند.
جدول Review را تنظیم کنید
نوع Review نشاندهندهی موجودیت نقد است و نوعهای User و Movie را در یک رابطهی چند به چند به هم مرتبط میکند (یک کاربر میتواند نقدهای زیادی بگذارد و هر فیلم میتواند نقدهای زیادی داشته باشد).
قطعه کد را کپی کرده و در فایل dataconnect/schema/schema.gql خود قرار دهید:
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")
}
نکات کلیدی:
- کاربر: به کاربری که نظر را ثبت کرده است اشاره میکند.
- فیلم: به فیلمی که در حال بررسی است اشاره میکند.
- reviewDate: به طور خودکار روی زمانی که نقد با استفاده از
@default(expr: "request.time")ایجاد میشود، تنظیم میشود.
فیلدهای تولید شده خودکار و پیشفرضها
این طرحواره از عباراتی مانند @default(expr: "uuidV4()") برای تولید خودکار شناسهها و مهرهای زمانی منحصر به فرد استفاده میکند. برای مثال، فیلد id در انواع Movie و Review هنگام ایجاد یک رکورد جدید به طور خودکار با یک UUID پر میشود.
حالا که طرحواره تعریف شده است، برنامه فیلم شما پایه محکمی برای ساختار دادهها و روابط خود دارد!
۵. برترین و جدیدترین فیلمها را بازیابی کنید

در این بخش، دادههای فیلم آزمایشی را در شبیهسازهای محلی وارد میکنید، سپس کانکتورها (queryها) و کد TypeScript را برای فراخوانی این کانکتورها در برنامه وب پیادهسازی میکنید. در پایان، برنامه شما قادر خواهد بود به صورت پویا فیلمهای برتر و جدیدترین فیلمها را مستقیماً از پایگاه داده دریافت و نمایش دهد.
دادههای شبیهسازیشدهی فیلم، بازیگر و نقد را وارد کنید
- در VSCode،
dataconnect/moviedata_insert.gqlباز کنید . مطمئن شوید که شبیهسازها در افزونهی Firebase Data Connect در حال اجرا هستند. - شما باید دکمهی «اجرا (محلی)» را در بالای فایل ببینید. برای وارد کردن دادههای فیلم آزمایشی به پایگاه دادهی خود، روی این دکمه کلیک کنید.

- برای تأیید اینکه دادهها با موفقیت اضافه شدهاند، ترمینال Data Connect Execution را بررسی کنید.

پیادهسازی کانکتور
-
dataconnect/movie-connector/queries.gqlرا باز کنید. یک کوئری پایهListMoviesرا در قسمت نظرات خواهید یافت: این کوئری تمام فیلمها و جزئیات آنها (برای مثال،query ListMovies @auth(level: PUBLIC) { movies { id title imageUrl releaseYear genre rating tags description } }id،title،releaseYear) را واکشی میکند. با این حال، فیلمها را مرتب نمیکند . - برای افزودن گزینههای مرتبسازی و محدودسازی، کوئری
ListMoviesموجود را با کوئری زیر جایگزین کنید :# 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 } } - برای اجرای کوئری در پایگاه داده محلی خود، روی دکمه Run (local) کلیک کنید. همچنین میتوانید متغیرهای کوئری را قبل از اجرا در پنل پیکربندی وارد کنید.

نکات کلیدی:
-
movies(): فیلد کوئری GraphQL برای واکشی دادههای فیلم از پایگاه داده. -
orderByRating: پارامتری برای مرتبسازی فیلمها بر اساس امتیاز (صعودی/نزولی). -
orderByReleaseYear: پارامتری برای مرتبسازی فیلمها بر اساس سال انتشار (صعودی/نزولی). -
limit: تعداد فیلمهای برگردانده شده را محدود میکند.
ادغام کوئریها در برنامه وب
در این بخش از آزمایشگاه کد، از کوئریهای تعریفشده در بخش قبلی در برنامه وب خود استفاده خواهید کرد. شبیهسازهای Firebase Data Connect بر اساس اطلاعات موجود در فایلهای .gql (بهطور خاص، schema.gql ، queries.gql ، mutations.gql ) و فایل connector.yaml SDK تولید میکنند. این SDKها را میتوان مستقیماً در برنامه شما فراخوانی کرد.
- در
MovieService(app/src/lib/MovieService.tsx)، عبارت import در بالا را از حالت کامنت خارج کنید : تابعimport { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect";listMovies، نوع پاسخListMoviesDataو متغیر شمارشیOrderDirectionهمگی SDKهایی هستند که توسط شبیهسازهای Firebase Data Connect بر اساس طرحواره و کوئریهایی که قبلاً تعریف کردهاید، تولید شدهاند. - توابع
handleGetTopMoviesوhandleGetLatestMoviesرا با کد زیر جایگزین کنید:// 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; } };
نکات کلیدی:
-
listMovies: یک تابع خودکار که کوئریlistMoviesرا برای بازیابی لیستی از فیلمها فراخوانی میکند. این شامل گزینههایی برای مرتبسازی بر اساس رتبهبندی یا سال انتشار و محدود کردن تعداد نتایج است. -
ListMoviesData: نوع نتیجهای که برای نمایش ۱۰ فیلم برتر و جدیدترین فیلمها در صفحه اصلی برنامه استفاده میشود.
آن را در عمل ببینید
برای مشاهدهی کوئری در عمل، برنامهی وب خود را مجدداً بارگذاری کنید. صفحهی اصلی اکنون به صورت پویا لیست فیلمها را نمایش میدهد و دادهها را مستقیماً از پایگاه دادهی محلی شما دریافت میکند. خواهید دید که فیلمهای برتر و جدیدترین فیلمها به طور یکپارچه نمایش داده میشوند و دادههایی را که اخیراً تنظیم کردهاید، منعکس میکنند.
۶. نمایش جزئیات فیلم و بازیگر
در این بخش، شما قابلیتی را برای بازیابی اطلاعات دقیق یک فیلم یا یک بازیگر با استفاده از شناسههای منحصر به فرد آنها پیادهسازی خواهید کرد. این کار نه تنها شامل واکشی دادهها از جداول مربوطه، بلکه شامل اتصال جداول مرتبط برای نمایش جزئیات جامع، مانند نقد فیلم و فیلمشناسی بازیگران نیز میشود.

پیادهسازی کانکتورها
-
dataconnect/movie-connector/queries.gqlرا در پروژه خود باز کنید . - برای بازیابی جزئیات فیلم و بازیگر، کوئریهای زیر را اضافه کنید :
# 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 } } } - تغییرات خود را ذخیره کنید و کوئریها را بررسی کنید.
نکات کلیدی:
-
movie()/actor(): فیلدهای کوئری GraphQL برای دریافت یک فیلم یا بازیگر از جدولMoviesیاActors. -
_on_: این امکان دسترسی مستقیم به فیلدها از یک نوع مرتبط که دارای رابطه کلید خارجی است را فراهم میکند. برای مثال،reviews_on_movieتمام نقدهای مربوط به یک فیلم خاص را واکشی میکند. -
_via_: برای پیمایش روابط چند به چند از طریق جدول پیوند استفاده میشود. برای مثال،actors_via_MovieActorاز طریق جدول پیوندMovieActorبه نوعActorدسترسی پیدا میکند و شرطwhereبازیگران را بر اساس نقش آنها (مثلاً "اصلی" یا "پشتیبان") فیلتر میکند.
با وارد کردن دادههای آزمایشی، پرسوجو را آزمایش کنید
- در پنل اجرای Data Connect، میتوانید با وارد کردن شناسههای ساختگی (mock IDs)، مانند موارد زیر، پرسوجو را آزمایش کنید:
{"id": "550e8400-e29b-41d4-a716-446655440000"} - برای بازیابی جزئیات مربوط به «پارادوکس کوانتومی» (فیلم ساختگی که شناسه فوق به آن مربوط میشود) روی Run (محلی) برای
GetMovieByIdکلیک کنید.

ادغام کوئریها در برنامه وب
- در
MovieService(app/src/lib/MovieService.tsx)، ایمپورتهای زیر را از حالت کامنت خارج کنید :import { getMovieById, GetMovieByIdData } from "@movie/dataconnect"; import { GetActorByIdData, getActorById } from "@movie/dataconnect"; - توابع
handleGetMovieByIdوhandleGetActorByIdرا با کد زیر جایگزین کنید :// 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; } };
نکات کلیدی:
-
getMovieById/getActorById: اینها توابع خودکار تولید شدهای هستند که کوئریهای تعریف شده توسط شما را فراخوانی میکنند و اطلاعات دقیقی را برای یک فیلم یا بازیگر خاص بازیابی میکنند. -
GetMovieByIdData/GetActorByIdData: اینها انواع نتایجی هستند که برای نمایش جزئیات فیلم و بازیگر در برنامه استفاده میشوند.
آن را در عمل ببینید
حالا، به صفحه اصلی برنامه وب خود بروید. روی یک فیلم کلیک کنید، و میتوانید تمام جزئیات آن، از جمله بازیگران و نقدها - اطلاعاتی که از جداول مرتبط استخراج شدهاند - را مشاهده کنید. به طور مشابه، کلیک روی یک بازیگر، فیلمهایی را که او در آنها حضور داشته است، نمایش میدهد.
۷. احراز هویت کاربر را مدیریت کنید
در این بخش، قابلیت ورود و خروج کاربر را با استفاده از احراز هویت Firebase پیادهسازی خواهید کرد. همچنین از دادههای احراز هویت Firebase برای بازیابی یا درج مستقیم دادههای کاربر در Firebase DataConnect استفاده خواهید کرد و مدیریت ایمن کاربر را در برنامه خود تضمین خواهید کرد.

پیادهسازی کانکتورها
-
mutations.gqlدرdataconnect/movie-connector/باز کنید . - برای ایجاد یا بهروزرسانی کاربر احراز هویتشدهی فعلی، جهش زیر را اضافه کنید:
# Create or update the current authenticated user mutation UpsertUser($username: String!) @auth(level: USER) { user_upsert( data: { id_expr: "auth.uid" username: $username } ) }
نکات کلیدی:
-
id_expr: "auth.uid": این ازauth.uidاستفاده میکند که مستقیماً توسط Firebase Authentication ارائه میشود، نه توسط کاربر یا برنامه، و با اطمینان از اینکه شناسه کاربر به طور ایمن و خودکار مدیریت میشود، یک لایه امنیتی اضافی اضافه میکند.
کاربر فعلی را دریافت کنید
-
queries.gqlدرdataconnect/movie-connector/باز کنید . - برای دریافت کاربر فعلی، کوئری زیر را اضافه کنید :
# 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 } } } } }
نکات کلیدی:
-
auth.uid: این مستقیماً از Firebase Authentication بازیابی میشود و دسترسی ایمن به دادههای خاص کاربر را تضمین میکند. - فیلدهای
_on_: این فیلدها نشاندهندهی جداول پیوند هستند:-
reviews_on_user: تمام نقدهای مربوط به کاربر، از جملهidوtitleفیلم را دریافت میکند. -
favorite_movies_on_user: تمام فیلمهایی که توسط کاربر به عنوان موارد دلخواه علامتگذاری شدهاند، از جمله اطلاعات دقیقی مانندgenre،releaseYear،ratingوmetadataبازیابی میکند.
-
ادغام کوئریها در برنامه وب
- در
MovieService(app/src/lib/MovieService.tsx)، ایمپورتهای زیر را از حالت کامنت خارج کنید:import { upsertUser } from "@movie/dataconnect"; import { getCurrentUser, GetCurrentUserData } from "@movie/dataconnect"; - توابع
handleAuthStateChangeوhandleGetCurrentUserرا با کد زیر جایگزین کنید:// 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; } };
نکات کلیدی:
-
handleAuthStateChange: این تابع به تغییرات وضعیت احراز هویت گوش میدهد. وقتی کاربر وارد سیستم میشود، دادههای کاربر را تنظیم میکند و جهشupsertUserرا برای ایجاد یا بهروزرسانی اطلاعات کاربر در پایگاه داده فراخوانی میکند. -
handleGetCurrentUser: با استفاده از کوئریgetCurrentUser، پروفایل کاربر فعلی را دریافت میکند که نظرات و فیلمهای مورد علاقه کاربر را بازیابی میکند.
آن را در عمل ببینید
حالا، روی دکمهی «ورود با گوگل» در نوار ناوبری کلیک کنید. میتوانید با استفاده از شبیهساز احراز هویت فایربیس وارد شوید. پس از ورود، روی «پروفایل من» کلیک کنید. فعلاً خالی خواهد بود، اما شما پایه و اساس مدیریت دادههای خاص کاربر را در برنامهی خود تنظیم کردهاید.
۸. تعاملات کاربر را پیادهسازی کنید
در این بخش از آزمایشگاه کد، تعاملات کاربر را در برنامه نقد فیلم پیادهسازی خواهید کرد، به طور خاص به کاربران اجازه میدهید فیلمهای مورد علاقه خود را مدیریت کنند و نقد بنویسند یا حذف کنند.

به کاربر اجازه دهید فیلمی را به عنوان مورد علاقه خود انتخاب کند
در این بخش، پایگاه داده را طوری تنظیم میکنید که به کاربران اجازه دهد یک فیلم را به لیست علاقهمندیهای خود اضافه کنند.
پیادهسازی کانکتورها
-
mutations.gqlدرdataconnect/movie-connector/باز کنید . - جهشهای زیر را برای مدیریت فیلمهای مورد علاقه اضافه کنید :
# 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 }) }
نکات کلیدی:
-
userId_expr: "auth.uid": ازauth.uidاستفاده میکند که مستقیماً توسط Firebase Authentication ارائه میشود و تضمین میکند که فقط به دادههای کاربر احراز هویت شده دسترسی یا تغییر داده میشود.
بررسی کنید که آیا یک فیلم در لیست علاقهمندیها قرار دارد یا خیر
-
queries.gqlدرdataconnect/movie-connector/باز کنید . - برای بررسی اینکه آیا یک فیلم در لیست علاقهمندیها قرار دارد یا خیر، کوئری زیر را اضافه کنید :
query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) { favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) { movieId } }
نکات کلیدی:
-
auth.uid: دسترسی امن به دادههای خاص کاربر را با استفاده از احراز هویت Firebase تضمین میکند. -
favorite_movie: جدول join مربوط بهfavorite_moviesرا بررسی میکند تا ببیند آیا یک فیلم خاص توسط کاربر فعلی به عنوان مورد علاقه علامتگذاری شده است یا خیر.
ادغام کوئریها در برنامه وب
- در
MovieService(app/src/lib/MovieService.tsx)، ایمپورتهای زیر را از حالت کامنت خارج کنید :import { addFavoritedMovie, deleteFavoritedMovie, getIfFavoritedMovie } from "@movie/dataconnect"; - توابع
handleAddFavoritedMovie،handleDeleteFavoritedMovieوhandleGetIfFavoritedMovieرا با کد زیر جایگزین کنید :// 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; } };
نکات کلیدی:
-
handleAddFavoritedMovieوhandleDeleteFavoritedMovie: از جهشها برای اضافه کردن یا حذف ایمن یک فیلم از موارد دلخواه کاربر استفاده کنید. -
handleGetIfFavoritedMovie: از کوئریgetIfFavoritedMovieبرای بررسی اینکه آیا یک فیلم توسط کاربر به عنوان مورد علاقه علامت گذاری شده است یا خیر، استفاده میکند.
آن را در عمل ببینید
اکنون، میتوانید با کلیک روی نماد قلب در کارتهای فیلم و صفحه جزئیات فیلم، فیلمها را به لیست علاقهمندیهایتان اضافه کنید یا از آنها صرف نظر کنید. علاوه بر این، میتوانید فیلمهای مورد علاقهتان را در صفحه پروفایلتان مشاهده کنید.
به کاربران اجازه دهید نظرات خود را بگذارند یا حذف کنند
در مرحله بعد، بخش مدیریت نظرات کاربران را در برنامه پیادهسازی خواهید کرد.
پیادهسازی کانکتورها
در mutations.gql ( dataconnect/movie-connector/mutations.gql ): جهشهای زیر را اضافه کنید:
# 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 })
}
نکات کلیدی:
-
userId_expr: "auth.uid": تضمین میکند که نقدها با کاربر احراز هویت شده مرتبط هستند. -
reviewDate_date: { today: true }: با استفاده از DataConnect به طور خودکار تاریخ فعلی را برای بررسی تولید میکند و نیاز به وارد کردن دستی را از بین میبرد.
ادغام کوئریها در برنامه وب
- در
MovieService(app/src/lib/MovieService.tsx)، ایمپورتهای زیر را از حالت کامنت خارج کنید :import { addReview, deleteReview } from "@movie/dataconnect"; - توابع
handleAddReviewوhandleDeleteReviewرا با کد زیر جایگزین کنید :// 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; } };
نکات کلیدی:
-
handleAddReview: جهشaddReviewرا برای افزودن یک نقد برای فیلم مشخص شده فراخوانی میکند و آن را به طور ایمن به کاربر احراز هویت شده پیوند میدهد. -
handleDeleteReview: از جهشdeleteReviewبرای حذف نقد یک فیلم توسط کاربر احراز هویت شده استفاده میکند.
آن را در عمل ببینید
کاربران اکنون میتوانند در صفحه جزئیات فیلم، برای فیلمها نقد بنویسند. همچنین میتوانند نقدهای خود را در صفحه پروفایلشان مشاهده و حذف کنند که به آنها امکان کنترل کامل بر تعاملاتشان با برنامه را میدهد.
۹. فیلترهای پیشرفته و تطبیق متن جزئی
در این بخش، قابلیتهای جستجوی پیشرفته را پیادهسازی خواهید کرد که به کاربران امکان میدهد فیلمها را بر اساس طیف وسیعی از رتبهبندیها و سالهای انتشار جستجو کنند، بر اساس ژانرها و برچسبها فیلتر کنند، تطبیق متن جزئی را در عناوین یا توضیحات انجام دهند و حتی چندین فیلتر را برای نتایج دقیقتر ترکیب کنند.

پیادهسازی کانکتورها
-
queries.gqlدرdataconnect/movie-connector/باز کنید. - برای پشتیبانی از قابلیتهای مختلف جستجو، کوئری زیر را اضافه کنید :
# 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 } } }
نکات کلیدی:
- عملگر
_and: چندین شرط را در یک کوئری ترکیب میکند و امکان فیلتر کردن جستجو بر اساس چندین فیلد مانندreleaseYear،ratingوgenreفراهم میکند. - عملگر
contains: به دنبال تطابقهای جزئی متن در فیلدها میگردد. در این پرسوجو، به دنبال تطابقهای درونtitle،description،nameیاreviewTextمیگردد. - عبارت
where: شرایط فیلتر کردن دادهها را مشخص میکند. هر بخش (فیلمها، بازیگران، نقدها) از یک عبارتwhereبرای تعریف معیارهای خاص جستجو استفاده میکند.
ادغام کوئریها در برنامه وب
- در
MovieService(app/src/lib/MovieService.tsx)، ایمپورتهای زیر را از حالت کامنت خارج کنید :import { searchAll, SearchAllData } from "@movie/dataconnect"; - تابع
handleSearchAllرا با کد زیر جایگزین کنید :// 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; } };
نکات کلیدی:
-
handleSearchAll: این تابع از کوئریsearchAllبرای انجام جستجو بر اساس ورودی کاربر استفاده میکند و نتایج را بر اساس پارامترهایی مانند سال، رتبهبندی، ژانر و تطابق جزئی متن فیلتر میکند.
آن را در عمل ببینید
از نوار ناوبری در برنامه وب به صفحه «جستجوی پیشرفته» بروید. اکنون میتوانید با استفاده از فیلترها و ورودیهای مختلف، فیلمها، بازیگران و نقدها را جستجو کنید و نتایج جستجوی دقیق و متناسب با سلیقه خود را دریافت کنید.
۱۰. اختیاری: استقرار در فضای ابری (پرداخت هزینه الزامی است)
حالا که مراحل توسعه محلی را پشت سر گذاشتهاید، وقت آن رسیده که طرحواره، دادهها و کوئریهای خود را روی سرور مستقر کنید. این کار را میتوان با استفاده از افزونه Firebase Data Connect VS Code یا Firebase CLI انجام داد.
طرح قیمتگذاری فایربیس خود را ارتقا دهید
برای ادغام Firebase Data Connect با Cloud SQL برای PostgreSQL، پروژه Firebase شما باید در طرح قیمتگذاری pay-as-you-go (Blaze) باشد، به این معنی که به یک حساب Cloud Billing متصل باشد.
- یک حساب Cloud Billing به یک روش پرداخت، مانند کارت اعتباری، نیاز دارد.
- اگر در استفاده از فایربیس و گوگل کلود تازهکار هستید، بررسی کنید که آیا واجد شرایط دریافت اعتبار ۳۰۰ دلاری و یک حساب کاربری رایگان ابری هستید یا خیر.
- اگر این codelab را به عنوان بخشی از یک رویداد انجام میدهید، از برگزارکننده خود بپرسید که آیا امکان استفاده از فضای ابری (Cloud credits) وجود دارد یا خیر.
برای ارتقاء پروژه خود به طرح Blaze، مراحل زیر را دنبال کنید:
- در کنسول Firebase، گزینه ارتقاء پلن خود را انتخاب کنید.
- طرح Blaze را انتخاب کنید. دستورالعملهای روی صفحه را دنبال کنید تا یک حساب Cloud Billing به پروژه شما متصل شود.
اگر به عنوان بخشی از این ارتقا نیاز به ایجاد یک حساب Cloud Billing داشتید، ممکن است لازم باشد برای تکمیل ارتقا، به روند ارتقا در کنسول Firebase برگردید.
برنامه وب خود را به پروژه Firebase خود وصل کنید
- برنامه وب خود را با استفاده از کنسول Firebase در پروژه Firebase خود ثبت کنید:
- پروژه خود را باز کنید و سپس روی افزودن برنامه کلیک کنید.
- فعلاً تنظیمات و پیکربندی SDK را نادیده بگیرید، اما حتماً شیء
firebaseConfigتولید شده را کپی کنید .

-
firebaseConfigموجود درapp/src/lib/firebase.tsxرا با پیکربندی که از کنسول Firebase کپی کردهاید، جایگزین کنید .const firebaseConfig = { apiKey: "API_KEY", authDomain: "PROJECT_ID.firebaseapp.com", projectId: "PROJECT_ID", storageBucket: "PROJECT_ID.firebasestorage.app", messagingSenderId: "SENDER_ID", appId: "APP_ID" }; - ساخت برنامه وب: به VS Code برگردید، در پوشه
app، از Vite برای ساخت برنامه وب جهت میزبانی استقرار استفاده کنید:cd app npm run build
احراز هویت فایربیس را در پروژه فایربیس خود تنظیم کنید
- احراز هویت فایربیس را با ورود به سیستم گوگل تنظیم کنید.

- (اختیاری) با استفاده از کنسول Firebase، دامنهها را برای احراز هویت Firebase مجاز کنید (برای مثال،
http://127.0.0.1).- در تنظیمات احراز هویت ، به دامنههای مجاز بروید.
- روی «افزودن دامنه» کلیک کنید و دامنه محلی خود را در لیست قرار دهید.

با Firebase CLI مستقر شوید
- در
dataconnect/dataconnect.yaml، مطمئن شوید که شناسه نمونه، پایگاه داده و شناسه سرویس شما با پروژه شما مطابقت دارند: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"] - مطمئن شوید که Firebase CLI را در پروژه خود تنظیم کردهاید:
npm i -g firebase-tools firebase login --reauth firebase use --add
- در ترمینال خود، دستور زیر را برای استقرار اجرا کنید:
firebase deploy --only dataconnect,hosting
- برای مقایسه تغییرات طرحواره خود، این دستور را اجرا کنید:
firebase dataconnect:sql:diff
- اگر تغییرات قابل قبول هستند، آنها را با موارد زیر اعمال کنید:
firebase dataconnect:sql:migrate
نمونه Cloud SQL برای PostgreSQL شما با طرحواره و دادههای نهایی پیادهسازی شده بهروزرسانی خواهد شد. میتوانید وضعیت را در کنسول Firebase رصد کنید.
اکنون باید بتوانید برنامه خود را به صورت زنده در your-project.web.app/ مشاهده کنید. علاوه بر این، میتوانید مانند کاری که با شبیهسازهای محلی انجام دادید، روی Run (Production) در پنل Firebase Data Connect کلیک کنید تا دادهها را به محیط تولید اضافه کنید.
۱۱. اختیاری: جستجوی برداری با Firebase Data Connect (پرداخت هزینه الزامی است)
در این بخش، شما با استفاده از Firebase Data Connect، جستجوی برداری را در برنامه نقد فیلم خود فعال خواهید کرد. این ویژگی امکان جستجوهای مبتنی بر محتوا، مانند یافتن فیلمهایی با توضیحات مشابه با استفاده از جاسازیهای برداری را فراهم میکند.
این مرحله مستلزم آن است که شما آخرین مرحله از این آزمایشگاه کد را برای استقرار در Google Cloud تکمیل کرده باشید.

طرحواره را بهروزرسانی کنید تا جاسازیها را برای یک فیلد در بر بگیرد
در dataconnect/schema/schema.gql ، فیلد descriptionEmbedding را به جدول 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
}
نکات کلیدی:
-
descriptionEmbedding: Vector @col(size:768): این فیلد، جاسازیهای معنایی توضیحات فیلم را ذخیره میکند و امکان جستجوی محتوای مبتنی بر بردار را در برنامه شما فراهم میکند.
فعال کردن هوش مصنوعی ورتکس
- برای راهاندازی APIهای Vertex AI از Google Cloud، راهنمای پیشنیازها را دنبال کنید. این مرحله برای پشتیبانی از تولید جاسازی و قابلیت جستجوی برداری ضروری است.
- با کلیک روی «استقرار در محیط تولید» با استفاده از افزونهی Firebase Data Connect VS Code، طرحوارهی خود را مجدداً مستقر کنید تا
pgvectorو جستجوی برداری فعال شوند.
پایگاه داده را با جاسازیها پر کنید
- پوشه
dataconnectرا در VS Code باز کنید . - برای پر کردن پایگاه داده خود با جاسازیهای فیلمها، روی Run(local) در
optional_vector_embed.gqlکلیک کنید.

یک جستجوی برداری اضافه کنید
در dataconnect/movie-connector/queries.gql ، کوئری زیر را برای انجام جستجوهای برداری اضافه کنید:
# 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
}
}
نکات کلیدی:
-
compare_embed: مدل جاسازی (textembedding-gecko@003) و متن ورودی ($query) را برای مقایسه مشخص میکند. -
method: روش شباهت (L2) را مشخص میکند که نشان دهنده فاصله اقلیدسی است. -
within: جستجو را به فیلمهایی با فاصله L2 برابر با ۲ یا کمتر محدود میکند و بر تطابقهای محتوایی نزدیک تمرکز میکند. -
limit: تعداد نتایج برگشتی را به ۵ محدود میکند.
تابع جستجوی برداری را در برنامه خود پیادهسازی کنید
حالا که طرحواره و پرسوجو تنظیم شدهاند، جستجوی برداری را در لایه سرویس برنامه خود ادغام کنید. این مرحله به شما امکان میدهد تا پرسوجوی جستجو را از برنامه وب خود فراخوانی کنید.
- در
app/src/lib/MovieService.ts، فایلهای ایمپورت شده زیر از SDKها را از حالت کامنت خارج کنید ، این کار مانند هر کوئری دیگری انجام خواهد شد.import { searchMovieDescriptionUsingL2similarity, SearchMovieDescriptionUsingL2similarityData, } from "@movie/dataconnect"; - تابع زیر را برای ادغام جستجوی مبتنی بر بردار به برنامه اضافه کنید :
// 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; } };
نکات کلیدی:
-
searchMoviesByDescription: این تابع، کوئریsearchMovieDescriptionUsingL2similarityرا فراخوانی میکند و متن ورودی را برای انجام جستجوی محتوای مبتنی بر بردار ارسال میکند.
آن را در عمل ببینید
به بخش «جستجوی برداری» در نوار ناوبری بروید و عباراتی مانند «عاشقانه و مدرن» را تایپ کنید. فهرستی از فیلمهایی را که با محتوای مورد نظر شما مطابقت دارند، مشاهده خواهید کرد، یا میتوانید به صفحه جزئیات فیلم هر فیلم بروید و بخش فیلمهای مشابه را در پایین صفحه بررسی کنید.

۱۲. نتیجهگیری
تبریک میگویم، شما باید بتوانید از برنامه وب استفاده کنید! اگر میخواهید با دادههای فیلم خودتان کار کنید، نگران نباشید، دادههای خودتان را با استفاده از افزونه Firebase Data Connect با تقلید از فایلهای _insert.gql وارد کنید، یا آنها را از طریق پنل اجرای Data Connect در VS Code اضافه کنید.