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 แบบจ่ายตามการใช้งานจริง
2. ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์
ในขั้นตอนนี้ของ 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 กับส่วนขยาย Firebase Data Connect VSCode ในส่วนขยาย ให้ทำดังนี้
- คลิกปุ่มลงชื่อเข้าใช้
- คลิกเชื่อมต่อโปรเจ็กต์ Firebase แล้วเลือกโปรเจ็กต์ Firebase
- เริ่มโปรแกรมจำลอง Firebase โดยใช้ส่วนขยาย Firebase Data Connect VS Code:
คลิกเริ่มโปรแกรมจำลอง แล้วตรวจสอบว่าโปรแกรมจำลองทำงานอยู่ในเทอร์มินัล
3. ตรวจสอบโค้ดเบสเริ่มต้น
ในส่วนนี้ คุณจะได้สำรวจส่วนสำคัญของโค้ดเบสเริ่มต้นของแอป แม้ว่าแอปจะไม่มีฟังก์ชันการทำงานบางอย่าง แต่ก็มีประโยชน์ในการทำความเข้าใจโครงสร้างโดยรวม
โครงสร้างโฟลเดอร์และไฟล์
ส่วนย่อยต่อไปนี้จะแสดงภาพรวมของโครงสร้างโฟลเดอร์และไฟล์ของแอป
ไดเรกทอรี 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 ในโปรเจ็กต์ Firebaselib/dataconnect-sdk/
: มี SDK ที่สร้างขึ้น คุณสามารถแก้ไขตำแหน่งการสร้าง SDK ในไฟล์connector/connector.yaml
และระบบจะสร้าง SDK โดยอัตโนมัติทุกครั้งที่คุณกำหนดการค้นหาหรือการเปลี่ยนแปลง
4. กำหนดสคีมาสำหรับรีวิวภาพยนตร์
ในส่วนนี้ คุณจะได้กำหนดโครงสร้างและความสัมพันธ์ระหว่างเอนทิตีหลักในแอปพลิเคชันภาพยนตร์ในสคีมา ระบบจะแมปเอนทิตี เช่น Movie
, User
, Actor
และ Review
กับตารางฐานข้อมูล โดยสร้างความสัมพันธ์โดยใช้ Firebase Data Connect และคำสั่งสคีมา GraphQL เมื่อพร้อมใช้งานแล้ว แอปของคุณจะพร้อมจัดการทุกอย่าง ตั้งแต่การค้นหาภาพยนตร์ยอดนิยมและการกรองตามประเภท ไปจนถึงการอนุญาตให้ผู้ใช้เขียนรีวิว ทำเครื่องหมายรายการโปรด สำรวจภาพยนตร์ที่คล้ายกัน หรือค้นหาภาพยนตร์แนะนำตามข้อความที่ป้อนผ่านการค้นหาเวกเตอร์
เอนทิตีและความสัมพันธ์หลัก
Movie
ประเภทนี้มีรายละเอียดสำคัญ เช่น ชื่อ ประเภท และแท็ก ซึ่งแอปใช้สำหรับการค้นหาและโปรไฟล์ภาพยนตร์ ประเภท User
จะติดตามการโต้ตอบของผู้ใช้ เช่น รีวิวและรายการโปรด 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
}
สิ่งสำคัญที่ได้เรียนรู้:
- ภาพยนตร์ @ref: อ้างอิง
Movie
type เพื่อสร้างความสัมพันธ์คีย์นอก
ตั้งค่าตาราง 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"
}
สิ่งสำคัญที่ได้เรียนรู้:
- ภาพยนตร์: อ้างอิงประเภทภาพยนตร์ สร้างคีย์ต่างประเทศ movieId: UUID! โดยนัย
- actor: อ้างอิงประเภท Actor โดยจะสร้างคีย์นอก actorId: UUID! โดยนัย
- role: กำหนดบทบาทของนักแสดงในภาพยนตร์ (เช่น "หลัก" หรือ "สนับสนุน")
ตั้งค่าตาราง 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: อ้างอิงประเภทภาพยนตร์ ซึ่งจะสร้างคีย์นอก
movieId: UUID!
โดยนัย - user: อ้างอิงประเภทผู้ใช้ สร้างคีย์นอก
userId: UUID!
โดยนัย
ตั้งค่าตาราง Review
ประเภท Review
แสดงถึงเอนทิตีรีวิวและลิงก์ประเภท User
และ Movie
ในความสัมพันธ์แบบกลุ่มต่อกลุ่ม (ผู้ใช้ 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: อ้างอิงถึงผู้ใช้ที่เขียนรีวิว
- ภาพยนตร์: อ้างอิงถึงภาพยนตร์ที่กำลังรีวิว
- reviewDate: ตั้งค่าโดยอัตโนมัติเป็นเวลาที่สร้างรีวิวโดยใช้
@default(expr: "request.time")
ฟิลด์และค่าเริ่มต้นที่สร้างขึ้นโดยอัตโนมัติ
สคีมาใช้การแสดงผล เช่น @default(expr: "uuidV4()")
เพื่อสร้างรหัสและการประทับเวลาที่ไม่ซ้ำกันโดยอัตโนมัติ เช่น ระบบจะป้อนข้อมูลในฟิลด์ id
ในประเภท Movie
และ Review
โดยอัตโนมัติด้วย UUID เมื่อสร้างระเบียนใหม่
ตอนนี้เมื่อกำหนดสคีมาแล้ว แอปภาพยนตร์ของคุณก็มีรากฐานที่มั่นคงสำหรับโครงสร้างและความสัมพันธ์ของข้อมูล
5. ดึงข้อมูลภาพยนตร์ยอดนิยมและล่าสุด
ในส่วนนี้ คุณจะแทรกข้อมูลภาพยนตร์จำลองลงในโปรแกรมจำลองในเครื่อง จากนั้นจะใช้ตัวเชื่อมต่อ (การค้นหา) และโค้ด TypeScript เพื่อเรียกตัวเชื่อมต่อเหล่านี้ในเว็บแอปพลิเคชัน เมื่อสิ้นสุดการดำเนินการ แอปจะดึงและแสดงภาพยนตร์ยอดนิยมและภาพยนตร์ล่าสุดจากฐานข้อมูลได้แบบไดนามิกโดยตรง
แทรกข้อมูลภาพยนตร์ นักแสดง และรีวิวจำลอง
- เปิด
dataconnect/moviedata_insert.gql
ใน VSCode ตรวจสอบว่าโปรแกรมจำลองในส่วนขยาย Firebase Data Connect ทำงานอยู่ - คุณควรเห็นปุ่มเรียกใช้ (ในเครื่อง) ที่ด้านบนของไฟล์ คลิกเพื่อแทรกข้อมูลภาพยนตร์จำลองลงในฐานข้อมูล
- ตรวจสอบเทอร์มินัลการดำเนินการเชื่อมต่อข้อมูลเพื่อยืนยันว่าเพิ่มข้อมูลสำเร็จแล้ว
ติดตั้งใช้งานเครื่องมือเชื่อมต่อ
- เปิด
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 } }
- คลิกปุ่มเรียกใช้ (ในเครื่อง) เพื่อเรียกใช้การค้นหาเทียบกับฐานข้อมูลในเครื่อง นอกจากนี้ คุณยังป้อนตัวแปรการค้นหาในแผงการกำหนดค่าก่อนเรียกใช้ได้ด้วย
สิ่งสำคัญที่ได้เรียนรู้:
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
และ EnumOrderDirection
ทั้งหมดเป็น SDK ที่จำลองเครื่องมือเชื่อมต่อข้อมูล Firebase สร้างขึ้นตามสคีมาและการค้นหาที่คุณกำหนดไว้ก่อนหน้านี้ - แทนที่ฟังก์ชัน
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 อันดับแรกและภาพยนตร์ล่าสุดในหน้าแรกของแอป
ดูการใช้งานจริง
โหลดเว็บแอปซ้ำเพื่อดูการทำงานของคำค้นหา ตอนนี้หน้าแรกจะแสดงรายการภาพยนตร์แบบไดนามิก โดยดึงข้อมูลจากฐานข้อมูลในเครื่องโดยตรง คุณจะเห็นภาพยนตร์ยอดนิยมและภาพยนตร์ล่าสุดปรากฏขึ้นอย่างราบรื่น ซึ่งสะท้อนถึงข้อมูลที่คุณเพิ่งตั้งค่า
6. แสดงรายละเอียดภาพยนตร์และนักแสดง
ในส่วนนี้ คุณจะใช้ฟังก์ชันเพื่อดึงข้อมูลโดยละเอียดของภาพยนตร์หรือนักแสดงโดยใช้รหัสที่ไม่ซ้ำกัน ซึ่งไม่เพียงแค่ดึงข้อมูลจากตารางที่เกี่ยวข้องเท่านั้น แต่ยังรวมถึงการรวมตารางที่เกี่ยวข้องเพื่อแสดงรายละเอียดที่ครอบคลุม เช่น รีวิวภาพยนตร์และผลงานภาพยนตร์ของนักแสดง
ติดตั้งใช้งานตัวเชื่อมต่อ
- เปิด
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
เข้าถึงActor
ประเภทผ่านตารางMovieActor
การเชื่อม และเงื่อนไขwhere
จะกรองนักแสดงตามบทบาท (เช่น "หลัก" หรือ "สมทบ")
ทดสอบคําค้นหาโดยป้อนข้อมูลจำลอง
- ในแผงการดำเนินการ 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
: ประเภทผลลัพธ์เหล่านี้ใช้เพื่อแสดงรายละเอียดภาพยนตร์และนักแสดงในแอป
ดูการใช้งานจริง
ตอนนี้ ให้ไปที่หน้าแรกของเว็บแอป คลิกภาพยนตร์ แล้วคุณจะดูรายละเอียดทั้งหมดของภาพยนตร์ได้ รวมถึงนักแสดงและรีวิว ซึ่งเป็นข้อมูลที่ดึงมาจากตารางที่เกี่ยวข้อง ในทำนองเดียวกัน การคลิกนักแสดงจะแสดงภาพยนตร์ที่นักแสดงรายนั้นเคยร่วมแสดง
7. จัดการการตรวจสอบสิทธิ์ผู้ใช้
ในส่วนนี้ คุณจะได้ใช้ฟังก์ชันการลงชื่อเข้าใช้และออกจากระบบของผู้ใช้โดยใช้ 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 โดยตรง ไม่ใช่จากผู้ใช้หรือแอป ซึ่งจะเพิ่มระดับความปลอดภัยอีกชั้นด้วยการตรวจสอบว่ามีการจัดการรหัสผู้ใช้อย่างปลอดภัยและโดยอัตโนมัติ
ดึงข้อมูลผู้ใช้ปัจจุบัน
- เปิด
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
: ดึงรีวิวทั้งหมดที่เกี่ยวข้องกับผู้ใช้ รวมถึง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
ซึ่งจะดึงข้อมูลรีวิวและภาพยนตร์ที่ผู้ใช้ชื่นชอบ
ดูการใช้งานจริง
ตอนนี้ ให้คลิกปุ่ม "ลงชื่อเข้าใช้ด้วย Google" ในแถบนำทาง คุณลงชื่อเข้าใช้ได้โดยใช้โปรแกรมจำลองการตรวจสอบสิทธิ์ Firebase หลังจากลงชื่อเข้าใช้แล้ว ให้คลิก "โปรไฟล์ของฉัน" ตอนนี้จะยังไม่มีข้อมูล แต่คุณได้วางรากฐานสำหรับการจัดการข้อมูลเฉพาะผู้ใช้ในแอปแล้ว
8. ใช้การโต้ตอบของผู้ใช้
ในส่วนนี้ของโค้ดแล็บ คุณจะได้ใช้การโต้ตอบของผู้ใช้ในแอปรีวิวภาพยนตร์ โดยเฉพาะการอนุญาตให้ผู้ใช้จัดการภาพยนตร์ที่ชื่นชอบ รวมถึงเขียนหรือลบรีวิว
อนุญาตให้ผู้ใช้เพิ่มภาพยนตร์ลงในรายการโปรด
ในส่วนนี้ คุณจะตั้งค่าฐานข้อมูลเพื่อให้ผู้ใช้เพิ่มภาพยนตร์ลงในรายการโปรดได้
ติดตั้งใช้งานตัวเชื่อมต่อ
- เปิด
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
mutation เพื่อเพิ่มรีวิวสำหรับภาพยนตร์ที่ระบุ โดยลิงก์รีวิวกับผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์อย่างปลอดภัยhandleDeleteReview
: ใช้การเปลี่ยนแปลงdeleteReview
เพื่อนำรีวิวภาพยนตร์ของผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์ออก
ดูการใช้งานจริง
ตอนนี้ผู้ใช้สามารถเขียนรีวิวภาพยนตร์ในหน้ารายละเอียดภาพยนตร์ได้แล้ว นอกจากนี้ ผู้ใช้ยังดูและลบรีวิวของตนเองในหน้าโปรไฟล์ได้ด้วย ซึ่งจะช่วยให้ผู้ใช้ควบคุมการโต้ตอบกับแอปได้อย่างเต็มที่
9. ตัวกรองขั้นสูงและการจับคู่ข้อความบางส่วน
ในส่วนนี้ คุณจะได้ใช้ความสามารถในการค้นหาขั้นสูง ซึ่งจะช่วยให้ผู้ใช้ค้นหาภาพยนตร์ตามช่วงคะแนนและปีที่เผยแพร่ กรองตามประเภทและแท็ก ทำการจับคู่ข้อความบางส่วนในชื่อหรือคำอธิบาย และแม้แต่รวมตัวกรองหลายรายการเพื่อให้ได้ผลลัพธ์ที่แม่นยำยิ่งขึ้น
ติดตั้งใช้งานตัวเชื่อมต่อ
- เปิด
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
clause: ระบุเงื่อนไขสำหรับการกรองข้อมูล แต่ละส่วน (ภาพยนตร์ นักแสดง รีวิว) ใช้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
เพื่อทำการค้นหาตามข้อมูลที่ผู้ใช้ป้อน โดยกรองผลลัพธ์ตามพารามิเตอร์ต่างๆ เช่น ปี การจัดประเภท ประเภท และข้อความที่ตรงกันบางส่วน
ดูการใช้งานจริง
ไปที่หน้า "การค้นหาขั้นสูง" จากแถบนำทางในเว็บแอป ตอนนี้คุณสามารถค้นหาภาพยนตร์ นักแสดง และรีวิวได้โดยใช้ตัวกรองและข้อมูลต่างๆ เพื่อรับผลการค้นหาที่ละเอียดและปรับแต่งแล้ว
10. ไม่บังคับ: ทำให้ใช้งานได้กับ Cloud (ต้องมีการเรียกเก็บเงิน)
ตอนนี้คุณได้ทำตามขั้นตอนการพัฒนาซ้ำในเครื่องแล้ว ก็ถึงเวลาที่จะนำสคีมา ข้อมูล และการค้นหาไปใช้กับเซิร์ฟเวอร์ ซึ่งสามารถทำได้โดยใช้ส่วนขยาย Firebase Data Connect สำหรับ VS Code หรือ Firebase CLI
อัปเกรดแพ็กเกจราคาของ Firebase
หากต้องการผสานรวม Firebase Data Connect กับ Cloud SQL สำหรับ PostgreSQL โปรเจ็กต์ Firebase ต้องอยู่ในแพ็กเกจราคาแบบจ่ายตามการใช้งาน (Blaze) ซึ่งหมายความว่าต้องลิงก์กับบัญชีการเรียกเก็บเงินในระบบคลาวด์
- บัญชีสำหรับการเรียกเก็บเงินของ Cloud ต้องมีวิธีการชำระเงิน เช่น บัตรเครดิต
- หากเพิ่งเริ่มใช้ Firebase และ Google Cloud โปรดตรวจสอบว่าคุณมีสิทธิ์รับเครดิต$300 และบัญชีสำหรับการเรียกเก็บเงินในระบบคลาวด์แบบทดลองใช้ฟรีหรือไม่
- หากคุณกำลังทำ Codelab นี้เป็นส่วนหนึ่งของกิจกรรม โปรดสอบถามผู้จัดว่ามีเครดิต Cloud ให้หรือไม่
หากต้องการอัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze ให้ทำตามขั้นตอนต่อไปนี้
- ในคอนโซล Firebase ให้เลือกอัปเกรดแพ็กเกจ
- เลือกแพ็กเกจ Blaze ทำตามวิธีการบนหน้าจอเพื่อลิงก์บัญชีสำหรับการเรียกเก็บเงินใน Cloud กับโปรเจ็กต์
หากคุณต้องสร้างบัญชีสำหรับการเรียกเก็บเงินใน Cloud เป็นส่วนหนึ่งของการอัปเกรดนี้ คุณอาจต้องกลับไปที่ขั้นตอนการอัปเกรดใน Firebase Console เพื่อทำการอัปเกรดให้เสร็จสมบูรณ์
เชื่อมต่อเว็บแอปกับโปรเจ็กต์ Firebase
- ลงทะเบียนเว็บแอปในโปรเจ็กต์ Firebase โดยใช้คอนโซล Firebase
- เปิดโปรเจ็กต์ แล้วคลิกเพิ่มแอป
- ตอนนี้ให้ข้ามการตั้งค่า SDK และการกำหนดค่าไปก่อน แต่โปรดคัดลอกออบเจ็กต์
firebaseConfig
ที่สร้างขึ้น
- แทนที่
firebaseConfig
ที่มีอยู่ในapp/src/lib/firebase.tsx
ด้วยการกำหนดค่าที่คุณเพิ่งคัดลอกจากคอนโซล Firebaseconst 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
- ตั้งค่า Firebase Authentication ด้วยการลงชื่อเข้าใช้ด้วย Google
- (ไม่บังคับ) อนุญาตโดเมนสำหรับการตรวจสอบสิทธิ์ 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/
นอกจากนี้ คุณยังคลิกเรียกใช้ (การผลิต) ในแผง Firebase Data Connect เพื่อเพิ่มข้อมูลลงในสภาพแวดล้อมการผลิตได้เช่นเดียวกับที่ทำกับโปรแกรมจำลองในเครื่อง
11. ไม่บังคับ: การค้นหาเวกเตอร์ด้วย Firebase Data Connect (ต้องมีการเรียกเก็บเงิน)
ในส่วนนี้ คุณจะเปิดใช้การค้นหาเวกเตอร์ในแอปรีวิวภาพยนตร์โดยใช้ Firebase Data Connect ฟีเจอร์นี้ช่วยให้ค้นหาตามเนื้อหาได้ เช่น ค้นหาภาพยนตร์ที่มีคำอธิบายคล้ายกันโดยใช้การฝังเวกเตอร์
ขั้นตอนนี้กำหนดให้คุณต้องทำขั้นตอนสุดท้ายของ Codelab นี้ให้เสร็จสมบูรณ์เพื่อนำไปใช้งานใน Google Cloud
อัปเดตสคีมาให้มี Embedding สำหรับฟิลด์
ใน 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 VS Code
ป้อนข้อมูลการฝังลงในฐานข้อมูล
- เปิดโฟลเดอร์
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 เท่ากับ 2 หรือน้อยกว่า โดยเน้นที่เนื้อหาที่ตรงกันอย่างใกล้ชิดlimit
: จำกัดจำนวนผลลัพธ์ที่แสดงเป็น 5 รายการ
ใช้ฟังก์ชันการค้นหาเวกเตอร์ในแอป
เมื่อตั้งค่าสคีมาและการค้นหาแล้ว ให้ผสานรวมการค้นหาเวกเตอร์เข้ากับเลเยอร์บริการของแอป ขั้นตอนนี้ช่วยให้คุณเรียกคำค้นหาจากเว็บแอปได้
- ใน
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
โดยส่งข้อความที่ป้อนเพื่อทำการค้นหาเนื้อหาตามเวกเตอร์
ดูการใช้งานจริง
ไปที่ส่วน "Vector Search" ในแถบนำทาง แล้วพิมพ์วลี เช่น "โรแมนติกและทันสมัย" คุณจะเห็นรายการภาพยนตร์ที่ตรงกับเนื้อหาที่กำลังค้นหา หรือไปที่หน้ารายละเอียดภาพยนตร์ของภาพยนตร์เรื่องใดก็ได้ แล้วดูส่วนภาพยนตร์ที่คล้ายกันที่ด้านล่างของหน้า
12. บทสรุป
ยินดีด้วย คุณควรจะใช้เว็บแอปได้แล้ว หากต้องการเล่นกับข้อมูลภาพยนตร์ของคุณเอง ไม่ต้องกังวล ให้แทรกข้อมูลของคุณเองโดยใช้ส่วนขยาย Firebase Data Connect ด้วยการเลียนแบบไฟล์ _insert.gql
หรือเพิ่มผ่านแผงการดำเนินการ Data Connect ใน VS Code