1. ก่อนที่คุณจะเริ่มต้น
ในโค้ดแล็บนี้ คุณจะได้ผสานรวม Firebase Data Connect กับฐานข้อมูล Cloud SQL เพื่อสร้างเว็บแอปรีวิวภาพยนตร์ แอปที่เสร็จสมบูรณ์จะแสดงให้เห็นว่า Firebase Data Connect ช่วยให้การสร้างแอปพลิเคชันที่ทำงานด้วย SQL เป็นเรื่องง่ายเพียงใด ซึ่งประกอบด้วยฟีเจอร์ต่อไปนี้
- การตรวจสอบสิทธิ์: ใช้การตรวจสอบสิทธิ์ที่กำหนดเองสำหรับการค้นหาและการดัดแปลงของแอป เพื่อให้มั่นใจว่ามีเพียงผู้ใช้ที่ได้รับอนุญาตเท่านั้นที่โต้ตอบกับข้อมูลของคุณได้
- สคีมา GraphQL: สร้างและจัดการโครงสร้างข้อมูลโดยใช้สคีมา GraphQL ที่ยืดหยุ่นซึ่งปรับให้เหมาะกับความต้องการของเว็บแอปรีวิวภาพยนตร์
- การค้นหาและการเปลี่ยนรูปแบบ SQL: ดึงข้อมูล อัปเดต และจัดการข้อมูลใน Cloud SQL โดยใช้การค้นหาและการเปลี่ยนรูปแบบที่ทำงานด้วย GraphQL
- การค้นหาขั้นสูงที่มีการจับคู่สตริงบางส่วน: ใช้ตัวกรองและตัวเลือกการค้นหาเพื่อค้นหาภาพยนตร์ตามช่องต่างๆ เช่น ชื่อ คำอธิบาย หรือแท็ก
- ไม่บังคับ: การผสานรวมการค้นหาเวกเตอร์: เพิ่มฟังก์ชันการค้นหาเนื้อหาโดยใช้การค้นหาเวกเตอร์ของ Firebase Data Connect เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่สมบูรณ์ตามข้อมูลและค่ากําหนด
ข้อกำหนดเบื้องต้น
คุณต้องมีความเข้าใจพื้นฐานเกี่ยวกับ JavaScript
สิ่งที่คุณจะได้เรียนรู้
- ตั้งค่า Firebase Data Connect ด้วยโปรแกรมจำลองในเครื่อง
- ออกแบบสคีมาข้อมูลโดยใช้ Data Connect และ GraphQL
- เขียนและทดสอบการค้นหาและการกลายพันธุ์ต่างๆ สําหรับแอปรีวิวภาพยนตร์
- ดูวิธีที่ Firebase Data Connect สร้างและใช้ SDK ในแอป
- ติดตั้งใช้งานสคีมาและจัดการฐานข้อมูลอย่างมีประสิทธิภาพ
สิ่งที่ต้องมี
- Git
- โค้ด Visual Studio
- ติดตั้ง Node.js โดยใช้ nvm-windows (Windows) หรือ nvm (macOS/Linux)
- สร้างโปรเจ็กต์ Firebase ในคอนโซล Firebase หากยังไม่ได้สร้าง
- (ไม่บังคับ) หากต้องการใช้การค้นหาเวกเตอร์ ให้อัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze
การตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์
ส่วนนี้จะแนะนำการตั้งค่าสภาพแวดล้อมเพื่อเริ่มสร้างแอปรีวิวภาพยนตร์โดยใช้ Firebase Data Connect
ขั้นตอนที่ 1: โคลนที่เก็บโปรเจ็กต์
เริ่มต้นด้วยการทำโคลนที่เก็บโปรเจ็กต์และติดตั้ง Dependency ที่จำเป็น
git clone https://github.com/firebaseextended/codelab-dataconnect-web cd codelab-dataconnect-web cd ./app && npm i npm run dev
- หลังจากเรียกใช้คําสั่งเหล่านี้แล้ว ให้เปิด http://localhost:5173 ในเบราว์เซอร์เพื่อดูเว็บแอปที่ทํางานในเครื่อง ซึ่งทำหน้าที่เป็นอินเทอร์เฟซส่วนหน้าสำหรับการสร้างแอปรีวิวภาพยนตร์และการโต้ตอบกับฟีเจอร์ต่างๆ
ขั้นตอนที่ 2: เปิดโปรเจ็กต์ใน Visual Studio Code
เปิดโฟลเดอร์ codelab-dataconnect-web
ที่โคลนโดยใช้ Visual Studio Code ซึ่งคุณจะกำหนดสคีมา เขียนการค้นหา และทดสอบฟังก์ชันการทำงานของแอปได้
ขั้นตอนที่ 3: ติดตั้งส่วนขยาย Firebase Data Connect ใน Visual Studio
หากต้องการใช้ฟีเจอร์ Data Connect ให้ติดตั้งส่วนขยาย Visual Studio สำหรับ Firebase Data Connect หรือติดตั้งจาก Visual Studio Code Marketplace หรือค้นหาภายใน VS Code
- หรือติดตั้งจาก Visual Studio Code Marketplace หรือค้นหาภายใน VS Code
ขั้นตอนที่ 4: สร้างโปรเจ็กต์ Firebase
ไปที่คอนโซล Firebase เพื่อสร้างโปรเจ็กต์ Firebase ใหม่หากยังไม่มี จากนั้นทำดังนี้ในส่วนขยาย Firebase Data Connect ของ VSCode
- คลิกปุ่มลงชื่อเข้าใช้
- คลิกเชื่อมต่อโปรเจ็กต์ Firebase แล้วเลือกโปรเจ็กต์ที่สร้างในคอนโซล Firebase
ขั้นตอนที่ 5: เริ่มโปรแกรมจำลอง Firebase
ในส่วนขยาย Firebase Data Connect ของ VSCode ให้คลิก "เริ่มโปรแกรมจำลอง" และตรวจสอบว่าโปรแกรมจำลองทํางานอยู่ในเทอร์มินัล
2. ตรวจสอบโค้ดฐานเริ่มต้น
ในส่วนนี้ คุณจะได้สำรวจส่วนสําคัญของโค้ดเริ่มต้นของแอป แม้ว่าแอปจะขาดฟังก์ชันบางอย่าง แต่การทำความเข้าใจโครงสร้างโดยรวมก็มีประโยชน์
โครงสร้างโฟลเดอร์และไฟล์
ภาพรวมโดยย่อของโครงสร้างโฟลเดอร์และไฟล์ของแอปมีดังนี้
dataconnect/
มีการกำหนดค่า Firebase Data Connect, ตัวเชื่อมต่อ (ซึ่งกำหนดการค้นหาและการดัดแปลง) และไฟล์สคีมา
schema/schema.gql
: กำหนดสคีมา GraphQLconnector/queries.gql
: คําค้นหาที่จําเป็นสําหรับแอปconnector/mutations.gql
: การกลายพันธุ์ที่จําเป็นสําหรับแอปconnector/connector.yaml:
ไฟล์การกําหนดค่าสําหรับการสร้าง SDK
app/src/
มีตรรกะแอปพลิเคชันและการทำงานกับ Firebase Data Connect
firebase.ts
: การกําหนดค่าเพื่อเชื่อมต่อกับแอป Firebase ในคอนโซลlib/dataconnect-sdk/
: โฟลเดอร์นี้มี SDK ที่สร้างขึ้น คุณสามารถแก้ไขตำแหน่งการสร้าง SDK ในไฟล์ connector/connector.yaml และระบบจะสร้าง SDK โดยอัตโนมัติทุกครั้งที่คุณกำหนดการค้นหาหรือการดัดแปลง
3. การกําหนดสคีมาสําหรับรีวิวภาพยนตร์
ในส่วนนี้ คุณจะต้องกำหนดโครงสร้างและความสัมพันธ์ระหว่างเอนทิตีหลักในแ��ปพลิเคชันภาพยนตร์ในสคีมา เอนทิตี เช่น Movie
, User
, Actor
และ Review
จะแมปกับตารางฐานข้อมูล โดยมีการสร้างความสัมพันธ์โดยใช้คำสั่ง Firebase Data Connect และคำสั่งสคีมา GraphQL เมื่อติดตั้งใช้งานแล้ว แอปของคุณจะพร้อมจัดการทุกอย่างตั้งแต่การค้นหาภาพยนตร์ที่ได้รับคะแนนสูงสุดและการกรองตามประเภท ไปจนถึงการอนุญาตให้ผู้ใช้แสดงความคิดเห็น เลือกรายการโปรด สํารวจภาพยนตร์ที่คล้ายกัน หรือค้นหาภาพยนตร์แนะนำตามข้อความที่ป้อนผ่านการค้นหาเวกเตอร์
เอนทิตีหลักและความสัมพันธ์
ประเภท Movie
มีรายละเอียดสำคัญ เช่น ชื่อ ประเภท และแท็ก ซึ่งแอปใช้สำหรับการค้นหาและโปรไฟล์ภาพยนตร์ ประเภท User
จะติดตามการโต้ตอบของผู้ใช้ เช่น รีวิวและรายการโปรด Reviews
เชื่อมต่อผู้ใช้กับภาพยนตร์ โดยให้แอปแสดงการให้คะแนนและความคิดเห็นที่ผู้ใช้สร้างขึ้น
ความสัมพันธ์ระหว่างภาพยนตร์ นักแสดง และผู้ใช้ทำให้แอปมีความหลากหลายมากขึ้น ตารางการรวม MovieActor
ช่วยแสดงรายละเอียดนักแสดงและผลงานภาพยนตร์ของนักแสดง ประเภท FavoriteMovie
ช่วยให้ผู้ใช้สามารถตั้งค่าภาพยนตร์เป็นรายการโปรด เพื่อให้แอปแสดงรายการโปรดที่ปรับเปลี่ยนในแบบของคุณและไฮไลต์รายการยอดนิยม
ตารางภาพยนตร์
ประเภท Movie จะกำหนดโครงสร้างหลักสำหรับเอนทิตีภาพยนตร์ ซึ่งรวมถึงช่องต่างๆ เช่น ชื่อ ประเภท ปีเผยแพร่ และการจัดประเภท
คัดลอกและวางข้อมูลโค้ดลงในไฟล์ 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]
}
สรุปประเด็นสำคัญ:
- id: UUID ที่ไม่ซ้ำกันสำหรับ��าพยนตร์แต่ละเรื่อง ซึ่งสร้างขึ้นโดยใช้
@default(expr: "uuidV4()")
ตาราง MovieMetadata
ประเภท MovieMetadata จะสร้างความสัมพันธ์แบบ 1:1 กับประเภท 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 โดยปริยาย
- role: กำหนดบทบาทของนักแสดงในภาพยนตร์ (เช่น "main" หรือ "supporting")
ตารางผู้ใช้
ประเภท User
จะกำหนดเอนทิตีผู้ใช้ที่โต้ตอบกับภาพยนตร์ด้วยการเขียนรีวิวหรือตั้งภาพยนตร์เป็นรายการโปรด
คัดลอกและวางข้อมูลโค้ดลงในไฟล์ dataconnect/schema/schema.gql
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
}
ตาราง 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 โดยปริยาย
- user: อ้างอิงประเภทผู้ใช้ ��ร���างคีย์ต่างประเทศ userId: UUID โดยนัย
ตารางรีวิว
ประเภทรีวิวแสดงถึงเอนทิตีรีวิวและลิงก์ประเภทผู้ใช้และภาพยนตร์ในความสัมพันธ์แบบหลายต่อหลายรายการ (ผู้ใช้ 1 คนสามารถเขียนรีวิวได้หลายรายการ และภาพยนตร์แต่ละเรื่องมีรีวิวได้หลายรายการ)
คัดลอกและวางข้อมูลโค้ดลงในไฟล์ 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")
}
สรุปประเด็นสำคัญ:
- user: อ้างอิงผู้ใช้ที่เขียนรีวิว
- movie: อ้างอิงภาพยนตร์ที่รีวิว
- reviewDate: ตั้งค่าเป็นเวลาที่สร้างรีวิวโดยอัตโนมัติโดยใช้
@default(expr: "request.time")
ฟิลด์และค่าเริ่มต้นที่สร้างขึ้นโดยอัตโนมัติ
สคีมาใช้นิพจน์อย่าง @default(expr: "uuidV4()")
เพื่อสร้างรหัสที่ไม่ซ้ำกันและการประทับเวลาโดยอัตโนมัติ ตัวอย่างเช่น ช่องรหัสในประเภทภาพยนตร์และรีวิวจะป้อนข้อมูล UUID โดยอัตโนมัติเมื่อมีการสร้างระเบียนใหม่
เมื่อกําหนดสคีมาแล้ว แอปภาพยนตร์ของคุณจะมีรากฐานที่มั่นคงสําหรับโครงสร้างและความสัมพันธ์ของข้อมูล
4. ดึงข้อมูลภาพยนตร์ยอดนิยมและภาพยนตร์ล่าสุด
ในส่วนนี้ คุณจะแทรกข้อมูลภาพยนตร์จำลองลงในโปรแกรมจำลองในเครื่อง จากนั้นใช้ตัวเชื่อมต่อ (การค้นหา) และโค้ด TypeScript เพื่อเรียกใช้ตัวเชื่อมต่อเหล่านี้ในเว็บแอปพลิเคชัน เมื่อดำเนินการเสร็จสิ้น แอปจะดึงข้อมูลและแสดงภาพยนตร์ยอดนิยมและภาพยนตร์ล่าสุดแบบไดนามิกจากฐานข้อมูลได้โดยตรง
การแทรกข้อมูลภาพยนตร์ นักแสดง และรีวิวจำลอง
- ใน VSCode ให้เปิด
dataconnect/moviedata_insert.gql
ตรวจสอบว่าโปรแกรมจําลองในชิ้นงาน Firebase Data Connect ทํางานอยู่ - คุณควรเห็นปุ่มเรียกใช้ (ในเครื่อง) ที่ด้านบนของไฟล์ คลิกเพื่อแทรกข้อมูลภาพยนตร์จำลองลงในฐานข้อมูล
- ตรวจสอบเทอร์มินัลการดำเนินการเชื่อมต่อข้อมูลเพื่อยืนยันว่าเพิ่มข้อมูลเรียบร้อยแล้ว
การใช้เครื่องมือเชื่อมต่อ
- เปิด
dataconnect/movie-connector/queries.gql
คุณจะเห็นการค้นหาListMovies
พื้นฐานในความคิดเห็น
query ListMovies @auth(level: PUBLIC) {
movies {
id
title
imageUrl
releaseYear
genre
rating
tags
description
}
}
การค้นหานี้จะดึงข้อมูลภาพยนตร์ทั้งหมดและรายละเอียดของภาพยนตร์ (เช่น รหัส ชื่อ ปีเผยแพร่) แต่จะไม่จัดเรียงภาพยนตร์
- แทนที่การค้นหา
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
}
}
คลิกปุ่มเรียกใช้ (ในเครื่อง) เพื่อเรียกใช้การค้นหากับฐานข้อมูลในเครื่อง นอกจากนี้ คุณยังป้อนตัวแปรการค้นหาในแผงการกําหนดค่าก่อนเรียกใช้ได้
สรุปประเด็นสำคัญ:
- movies(): ช่องการค้นหา GraphQL สำหรับการดึงข้อมูลภาพยนตร์จากฐานข้อมูล
- orderByRating: พารามิเตอร์สำหรับจัดเรียงภาพยนตร์ตามการจัดประเภท (จากน้อยไปมาก/มากไปน้อย)
- orderByReleaseYear: พารามิเตอร์สำหรับจัดเรียงภาพยนตร์ตามปีที่ออกฉาย (จากน้อยไปมาก/มากไปน้อย)
- limit: จำกัดจำนวนภาพยนตร์ที่แสดง
การผสานรวมการค้นหาในเว็บแอป
ในส่วนนี้ คุณจะใช้การค้นหาที่กําหนดไว้ในส่วนก่อนหน้าในเว็บแอป เครื่องจำลอง Firebase Data Connect จะสร้าง SDK ตามข้อมูลในไฟล์ .gql (schema.gql, queries.gql, mutations.gql) และ connector.yaml คุณเรียกใช้ SDK เหล่านี้ได้โดยตรงในแอปพลิเคชัน
- ใน
MovieService
(app/src/lib/MovieService.tsx
) ให้ยกเลิกการคอมเมนต์คำสั่งการนําเข้าที่ด้านบน
import { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect";
ฟังก์ชัน listMovies
, ประเภทคำตอบ ListMoviesData
และ enum 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: ประเภทผลลัพธ์ที่ใช้แสดงภาพยนตร์ยอดนิยม 10 อันดับแรกและภาพยนตร์ล่าสุดในหน้าแรก
ดูการใช้งานจริง
โหลดเว็บแอปซ้ำเพื่อดูการค้นหา ตอนนี้หน้าแรกจะแสดงรายการภาพยนตร์แบบไดนามิก โดยดึงข้อมูลจากฐานข้อมูลในเครื่องโดยตรง คุณจะเห็นภาพยนตร์ยอดนิยมและภาพยนตร์ล่าสุดปรากฏขึ้นอย่างราบรื่น ซึ่งแสดงข้อมูลที่คุณเพิ่งตั้งค่า
5. การแสดงรายละเอียดภาพยนตร์และนักแสดง
ในส่วนนี้ คุณจะใช้ฟังก์ชันการทำ��านเพื่อดึงข้อมูลโดยละเอียดของภาพยนตร์หรือนักแสดงโดยใช้รหัสที่ไม่ซ้ำกัน ซึ่งไม่เพียงแต่จะดึงข้อมูลจากตารางที่เกี่ยวข้องเท่านั้น แต่ยังรวมตารางที่เกี่ยวข้องเพื่อแสดงรายละเอียดที่ครอบคลุม เช่น รีวิวภาพยนตร์และผลงานภาพยนตร์ของนักแสดง
การใช้เครื่องมือเชื่อมต่อ
- เปิด
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 สำหรับการดึงข้อมูลภาพยนตร์หรือนักแสดงรายการเดียวจากตารางภาพยนตร์หรือนักแสดง_on_
: ตัวเลือกนี้ช่วยให้เข้าถึงฟิลด์จากประเภทที่เชื่อมโยงซึ่งมีความสัมพันธ์ของคีย์ต่างประเทศได้โดยตรง เช่นreviews_on_movie
จะดึงข้อมูลรีวิวทั้งหมดที่เกี่ยวข้องกับภาพยนตร์หนึ่งๆ_via_
: ใช้เพื่อไปยังส่วนต่างๆ ของความสัมพันธ์แบบหลายต่อหลายรายการผ่านตารางการรวม ตัวอย่างเช่นactors_via_MovieActor
จะเข้าถึงประเภทนักแสดงผ่านตารางการรวม MovieActor และเงื่อนไขwhere
จะกรองนักแสดงตามบทบาท (เช่น "main" หรือ "supporting")
ในแผงการดําเนินการของ Data Connect คุณสามารถทดสอบการค้นหาได้โดยป้อนรหัสจำลอง เช่น
{"id": "550e8400-e29b-41d4-a716-446655440000"}
คลิกเรียกใช้ (ในเ��รื่อง) สำหรับ GetMovieById
เพื่อเรียกข้อมูลเกี่ยวกับ "Quantum Paradox" (ภาพยนตร์จำลองที่รหัสข้างต้นเกี่ยวข้อง)
การผสานรวมการค้นหาในเว็บแอป
- ใน
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
: ประเภทผลลัพธ์เหล่านี้ใช้เพื่อแสดงรายละเอียดภาพยนตร์และนักแสดงในแอป
ดูการใช้งานจริง
จากนั้นไปที่หน้าแรกของเว็บแอป คลิกภาพยนตร์เพื่อดูรายละเอียดทั้งหมด รวมถึงนักแสดงและรีวิว ซึ่งเป็นข้อมูลที่ดึงมาจากตารางที่เกี่ยวข้อง ในทำนองเดียวกัน การคลิกที่นักแสดงจะแสดงภาพยนตร์ที่นักแสดงคนนั้นแสดง
6. การจัดการการตรวจสอบสิทธิ์ของผู้ใช้
ในส่วนนี้ คุณจะใช้ฟังก์ชันการลงชื่อเข้าใช้และออกจากระบบของผู้ใช้โดยใช้ Firebase Authentication นอกจากนี้ คุณจะใช้ข้อมูลการตรวจสอบสิทธิ์ 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 โดยตรง เพื่อให้มั่นใจว่าเข้าถึงข้อมูลเฉพาะผู้ใช้ได้อย่างปลอดภัย_on_
ฟิลด์: ฟิลด์เหล่านี้แสดงตารางการเข้าร่วมreviews_on_user
: ดึงข้อมูลรีวิวทั้งหมดที่เกี่ยวข้องกับผู้ใช้ ซึ่งรวมถึงรหัสและชื่อภาพยนตร์favorite_movies_on_user
: ดึงข้อมูลภาพยนตร์ทั้งหมดที่ผู้ใช้ทำเครื่องหมายว่าชื่นชอบ รวมถึงข้อมูลโดยละเอียด เช่น ประเภท ปี การจัดประเภท และข้อมูลเมตา
การผสานรวมการค้นหาในเว็บแอป
- ใน 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
mutation เพื่อสร้างหรืออัปเดตข้อมูลของผู้ใช้ในฐานข้อมูลhandleGetCurrentUser
: ดึงข้อมูลโปรไฟล์ของผู้ใช้ปัจจุบันโดยใช้การค้นหาgetCurrentUser
ซึ่งจะดึงข้อมูลรีวิวและภาพยนตร์โปรดของผู้ใช้
ดูการใช้งานจริง
ตอนนี้ให้คลิกปุ่ม "ลงชื่อเข้าใช้ด้วย Google" ในแถบนําทาง คุณลงชื่อเข้าใช้ได้โดยใช้โปรแกรมจำลอง Firebase Auth หลังจากลงชื่อเข้าใช้แล้ว ให้คลิก "โปรไฟล์ของฉัน" ขณะนี้ส่วนนี้จะว่างเปล่า แต่คุณได้สร้างรากฐานสำหรับการจัดการข้อมูลที่เจาะจงผู้ใช้ในแอปแล้ว
7. การติดตั้งใช้งานการโต้ตอบของผู้ใช้
ในส่วนนี้ คุณจะใช้การโต้ตอบของผู้ใช้ในแอปรีวิวภาพยนตร์ ซึ่งจะช่วยให้ผู้ใช้จัดการภาพยนตร์ที่ชอบ รวมถึงเขียนหรือลบรีวิวได้
การใช้เครื่องมือเชื่อมต่อ
- เปิด
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
: ช่วยให้เข้าถึงข้อมูลที่เจาะจงผู้ใช้ได้อย่างปลอดภัยโดยใช้การตรวจสอบสิทธิ์ Firebasefavorite_movie
: ตรวจสอบตารางการเข้าร่วม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
เพื่อนำรีวิวภาพยนตร์ของผู้ใช้ที่ตรวจสอบสิทธิ์ออก
ดูการใช้งานจริง
ตอนนี้ผู้ใช้สามารถเขียนรีวิวภาพยนตร์ในหน้ารายละเอียดภาพยนตร์ได้แล้ว นอกจากนี้ ผู้ใช้ยังดูและลบรีวิวของตนเองในหน้าโปรไฟล์ได้ด้วย ซึ่งช่วยให้ผู้ใช้ควบคุมการโต้ตอบกับแอปได้อย่างเต็มรูปแบบ
8. ตัวกรองขั้นสูงและการจับคู่ข้อความบางส่วน
ในส่วนนี้ คุณจะใช้ความสามารถในการค้นหาขั้นสูง ซึ่งช่วยให้ผู้ใช้ค้นหาภาพยนตร์ตามการจัดประเภทและปีที่เผยแพร่ที่หลากหลาย กรองตามประเภทและแท็ก ทำการจับคู่ข้อความบางส่วนในชื่อหรือคำอธิบาย และแม้แต่รวมตัวกรองหลายรายการเข้าด้วยกันเพื่อให้ได้ผลลัพธ์ที่แม่นยำยิ่งขึ้น
การใช้เครื่องมือเชื่อมต่อ
- เปิด
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
เพื่อค้นหาตามข้อมูลที่ผู้ใช้ป้อน โดยกรองผลลัพธ์ตามพารามิเตอร์ต่างๆ เช่น ปี การให้คะแนน ประเภท และการจับคู่ข้อความบางส่วน
ดูการใช้งานจริง
ไปที่หน้า "การค้นหาขั้นสูง" จากแถบนาบในเว็บแอป ตอนนี้คุณค้นหาภาพยนตร์ นักแสดง และรีวิวได้โดยใช้ตัวกรองและอินพุตต่างๆ เพื่อรับผลการค้นหาที่ละเอียดและปรับให้เหมาะกับคุณ
9. ไม่บังคับ: ติดตั้งใช้งานในระบบคลาวด์ (ต้องมีการเรียกเก็บเงิน)
เมื่อคุณทําซ้ำการพัฒนาซอฟต์แวร์ภายในแล้ว ก็ถึงเวลาที่จะติดตั้งสคีมา ข้อมูล และการค้นหาลงในเซิร์ฟเวอร์ ซึ่งทําได้โดยใช้ส่วนขยาย Firebase Data Connect ใน VS Code หรือ Firebase CLI
การเพิ่มเว็บแอปในคอนโซล Firebase
- สร้างเว็บแอปในคอนโซล Firebase และจดรหัสแอปไว้
- ตั้งค่าเว็บแอปในคอนโซล Firebase โดยคลิก "เพิ่มแอป" คุณไม่จำเป็นต้องสนใจการตั้งค่า SDK และการกำหนดค่าในตอนนี้ แต่ให้จดจำออบเจ็กต์
firebaseConfig
ที่สร้างขึ้น - แทนที่
firebaseConfig
ในapp/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" };
- สร้างเว็บแอป: ในโฟลเดอร์
app
ให้ใช้ Vite เพื่อสร้างเว็บแอปสําหรับการทําให้การโฮสต์ใช้งานได้ โดยทําดังนี้
cd app npm run build
ตั้งค่าการตรวจสอบสิทธิ์ Firebase ในคอนโซล
- ตั้งค่า Firebase Auth ด้วย Google Sign-In
- (ไม่บังคับ) อนุญาตโดเมนสําหรับ (Firebase Auth) [https://firebase.google.com/docs/auth/web/hosting] ในคอนโซลโปรเจ็กต์ (เช่น
http://127.0.0.1
):
- ในการตั้งค่าการตรวจสอบสิทธิ์ ให้เลือกโปรเจ็กต์แล้วไปที่ (โดเมนที่ได้รับอนุญาต) [https://firebase.google.com/docs/auth/web/hosting] คลิก "เพิ่มโดเมน" และใส่โดเมนในเครื่องของคุณไว้ในรายการ
ทำให้ใช้งานได้ด้วย 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 for PostgreSQL จะอัปเดตด้วยสคีมาและข้อมูลที่ติดตั้งใช้งานแล้วในขั้นสุดท้าย คุณสามารถตรวจสอบสถานะได้ในคอนโซล Firebase
ตอนนี้คุณควรเห����แ��������������ณ�����ยแพร่�����ู่ที่ your-project.web.app/
นอกจากนี้ คุณยังคลิกเรียกใช้ (เวอร์ชันที่ใช้งานจริง) ในแผง Firebase Data Connect ได้ เช่นเดียวกับที่ทำกับโปรแกรมจำลองในเครื่อง เพื่อเพิ่มข้อมูลลงในสภาพแวดล้อมเวอร์ชันที่ใช้งานจริง
10. ไม่บังคับ: การค้นหาเวกเตอร์ด้วย Firebase Data Connect
ในส่วนนี้ คุณจะเปิดใช้การค้นหาเวกเตอร์ในแอปรีวิวภาพยนตร์โดยใช้ Firebase Data Connect ฟีเจอร์นี้ช่วยให้ค้นหาตามเนื้อหาได้ เช่น ค้นหาภาพยนตร์ที่มีคำอธิบายคล้ายกันโดยใช้การฝังเวกเตอร์
อัปเดตสคีมาให้รวมการฝังสำหรับช่อง
- ใน
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)
: ช่องนี้จะจัดเก็บการฝังเชิงความหมายของคำอธิบายภาพยนตร์ ซึ่งช่วยให้ค้นหาเนื้อหาตามเวกเตอร์ในแอปได้
การเปิดใช้งาน Vertex AI
- ทําตามคําแนะนําเบื้องต้นเพื่อตั้งค่า Vertex AI API ด้วย Google Cloud ขั้นตอนนี้เป็นขั้นตอนสําคัญในการสนับสนุนฟังก์ชันการสร้างการฝังและเวกเตอร์การค้นหา
- ทำให้สคีมาใช้งานได้อีกครั้งเพื่อเปิดใช้งาน
pgvector
และการค้นหาเวกเตอร์โดยคลิก "ทำให้ใช้งานได้จริง" โดยใช้ส่วนขยาย Firebase Data Connect ใน VSCode
การป้อนข้อมูลฐานข้อมูลด้วยเนื้อหาที่ฝัง
- เปิดโฟลเดอร์
dataconnect
ใน VSCode แล้วคลิกเรียกใช้(ในเครื่อง) ใน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 ไม่เกิน 2 โดยเน้นที่เนื้อหาที่ตรงกันมากlimit
: จำกัดจำนวนผลลัพธ์ที่แสดงผลเป็น 5 รายการ
ใช้ฟังก์ชันการค้นหาเวกเตอร์ในแอป
- ใน
app/src/lib/MovieService.ts
ให้ยกเลิกการคอมเมนต์การนําเข้าต่อไปนี้
ใช้ฟังก์ชันการค้นหาเวกเตอร์ในแอป
เมื่อตั้งค่าสคีมาและคําค้นหาแล้ว ให้ผสานรวมการค้นหาเวกเตอร์เข้ากับเลเยอร์บริการของแอป ขั้นตอนนี้ช่วยให้คุณเรียกใช้คำค้นหาจากเว็บแอปได้
ใน 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
โดยส่งข้อความที่ป้อนเพื่อค้นหาเนื้อหาตามเวกเตอร์
ดูการใช้งานจริง
ไปที่ส่วน "การค้นหาเวกเตอร์" ในแถบนาบ และพิมพ์วลีอย่าง "โรแมนติกและทันสมัย" คุณจะเห็นรายการภาพยนตร์ที่ตรงกับเนื้อหาที่คุณค้นหา หรือไปที่หน้ารายละเอียดภาพยนตร์ของภาพยนตร์เรื่องใดก็ได้ แล้วดูส่วนภาพยนตร์ที่คล้ายกันซึ่งอยู่ด้านล่างของหน้า
11. บทสรุป
ยินดีด้วย คุณควรใช้เว็บแอปได้แล้ว หากต้องการเล่นกับข้อมูลภาพยนตร์ของคุณเอง ไม่ต้องกังวล เพียงแทรกข้อมูลของคุณเองโดยใช้ส่วนขยาย FDC โดยเลียนแบบไฟล์ _insert.gql หรือเพิ่มผ่านแผงการดำเนินการของ Data Connect