สร้างด้วย Firebase Data Connect

1. ก่อนเริ่มต้น

แอป FriendlyMovies

ในโค้ดแล็บนี้ คุณจะได้ผสานรวม 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. ตั้งค่าสภาพแวดล้อมการพัฒนา

ระยะนี้ของโค้ดแล็บจะแนะนำการตั้งค่าสภาพแวดล้อมเพื่อเริ่มสร้างแอปรีวิวภาพยนตร์โดยใช้ Firebase Data Connect

  1. โคลนที่เก็บโปรเจ็กต์และติดตั้งไลบรารีที่จำเป็น
    git clone https://github.com/firebaseextended/codelab-dataconnect-web
    cd codelab-dataconnect-web
    cd ./app && npm i
    npm run dev
    
  2. หลังจากเรียกใช้คําสั่งเหล่านี้แล้ว ให้เปิด http://localhost:5173 ในเบราว์เซอร์เพื่อดูเว็บแอปที่ทํางานในเครื่อง หน้านี้เป็นหน้าเว็บสำหรับสร้างแอปรีวิวภาพยนตร์และโต้ตอบกับฟีเจอร์ต่างๆ93f6648a2532c606.png
  3. เปิดโฟลเดอร์ codelab-dataconnect-web ที่โคลนโดยใช้ Visual Studio Code ซึ่งคุณจะกำหนดสคีมา เขียนการค้นหา และทดสอบฟังก์ชันการทำงานของแอป
  4. หากต้องการใช้ฟีเจอร์ Data Connect ให้ติดตั้งส่วนขยาย Firebase Data Connect ใน Visual Studio
    หรือจะติดตั้งส่วนขยายจาก Visual Studio Code Marketplace หรือค้นหาภายใน VS Code ก็ได้b03ee38c9a81b648.png
  5. เปิดหรือสร้างโปรเจ็กต์ Firebase ใหม่ในคอนโซล Firebase
  6. เชื่อมต่อโปรเจ็กต์ Firebase กับส่วนขยาย Firebase Data Connect ใน VSCode ในส่วนขยาย ให้ทําดังนี้
    1. คลิกปุ่มลงชื่อเข้าใช้
    2. คลิกเชื่อมต่อโปรเจ็กต์ Firebase แล้วเลือกโปรเจ็กต์ Firebase
    4bb2fbf8f9fac29b.png
  7. เริ่มโปรแกรมจำลอง Firebase โดยใช้ส่วนขยาย Firebase Data Connect ใน VS Code โดย
    คลิกเริ่มโปรแกรมจำลอง แล้วตรวจสอบว่าโปรแกรมจำลองทำงานอยู่ในเทอร์มินัล6d3d95f4cb708db1.png

3. ตรวจสอบโค้ดฐานเริ่มต้น

ในส่วนนี้ คุณจะได้สำรวจส่วนสําคัญของโค้ดเริ่มต้นของแอป แม้ว่าแอปจะขาดฟังก์ชันบางอย่าง แต่การทำความเข้าใจโครงสร้างโดยรวมก็มีประโยชน์

โครงสร้างโฟลเดอร์และไฟล์

ส่วนย่อยต่อไปนี้แสดงภาพรวมของโครงสร้างโฟลเดอร์และไฟล์ของแอป

ไดเรกทอรี 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 โดยอัตโนมัติทุกครั้งที่คุณกำหนดการค้นหาหรือการกลายพันธุ์

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]
}

สรุปประเด็นสำคัญ:

  • 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

ประเภท 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! โดยนัย

ตั้งค่าตาราง 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: อ้างอิงผู้ใช้ที่เขียนรีวิว
  • movie: อ้างอิงภาพยนตร์ที่รีวิว
  • reviewDate: ตั้งค่าเป็นเวลาที่สร้างรีวิวโดยอัตโนมัติโดยใช้ @default(expr: "request.time")

ฟิลด์และค่าเริ่มต้นที่สร้างขึ้นโดยอัตโนมัติ

สคีมาใช้นิพจน์อย่าง @default(expr: "uuidV4()") เพื่อสร้างรหัสที่ไม่ซ้ำกันและการประทับเวลาโดยอัตโนมัติ ตัวอย่างเช่น ระบบจะป้อนข้อมูล UUID ลงในช่อง id ของประเภท Movie และ Review โดยอัตโนมัติเมื่อสร้างระเบียนใหม่

เมื่อกําหนดสคีมาแล้ว แอปภาพยนตร์ของคุณจะมีรากฐานที่มั่นคงสําหรับโครงสร้างและความสัมพันธ์ของข้อมูล

5. ดึงข้อมูลภาพยนตร์ยอดนิยมและภาพยนตร์ล่าสุด

แอป FriendlyMovies

ในส่วนนี้ คุณจะแทรกข้อมูลภาพยนตร์จำลองลงในโปรแกรมจำลองในเครื่อง จากนั้นใช้ตัวเชื่อมต่อ (การค้นหา) และโค้ด TypeScript เพื่อเรียกใช้ตัวเชื่อมต่อเหล่านี้ในเว็บแอปพลิเคชัน เมื่อดำเนินการเสร็จสิ้น แอปจะดึงข้อมูลและแสดงภาพยนตร์ยอดนิยมและภาพยนตร์ล่าสุดแบบไดนามิกจากฐานข้อมูลได้โดยตรง

แทรกข้อมูลจำลองของภาพยนตร์ นักแสดง และรีวิว

  1. ใน VSCode ให้เปิด dataconnect/moviedata_insert.gql ตรวจสอบว่าโปรแกรมจําลองในส่วนขยาย Firebase Data Connect ทํางานอยู่
  2. คุณควรเห็นปุ่มเรียกใช้ (ในเครื่อง) ที่ด้านบนของไฟล์ คลิกเพื่อแทรกข้อมูลภาพยนตร์จำลองลงในฐานข้อมูล
    e424f75e63bf2e10.png
  3. ตรวจสอบเทอร์มินัลการดำเนินการเชื่อมต่อข้อมูลเพื่อยืนยันว่าเพิ่มข้อมูลเรียบร้อยแล้ว
    e0943d7704fb84ea.png

ติดตั้งใช้งานเครื่องมือเชื่อมต่อ

  1. เปิด dataconnect/movie-connector/queries.gql คุณจะเห็นการค้นหา ListMovies พื้นฐานในความคิดเห็น ดังนี้
    query ListMovies @auth(level: PUBLIC) {
      movies {
        id
        title
        imageUrl
        releaseYear
        genre
        rating
        tags
        description
      }
    }
    
    ข้อความค้นหานี้จะดึงข้อมูลภาพยนตร์ทั้งหมดและรายละเอียดของภาพยนตร์ (เช่น id, title, releaseYear) แต่ไม่จัดเรียงภาพยนตร์
  2. แทนที่การค้นหา 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
      }
    }
    
  3. คลิกปุ่มเรียกใช้ (ในเครื่อง) เพื่อเรียกใช้การค้นหากับฐานข้อมูลในเครื่อง นอกจากนี้ คุณยังป้อนตัวแปรการค้นหาในแผงการกําหนดค่าก่อนเรียกใช้ได้
    c4d947115bb11b16.png

สรุปประเด็นสำคัญ:

  • movies(): ช่องการค้นหา GraphQL สำหรับการดึงข้อมูลภาพยนตร์จากฐานข้อมูล
  • orderByRating: พารามิเตอร์สำหรับจัดเรียงภาพยนตร์ตามการจัดประเภท (จากน้อยไปมาก/จากมากไปน้อย)
  • orderByReleaseYear: พารามิเตอร์สำหรับจัดเรียงภาพยนตร์ตามปีเผยแพร่ (จากน้อยไปมาก/จากมากไปน้อย)
  • limit: จำกัดจำนวนภาพยนตร์ที่แสดง

ผสานรวมการค้นหาในเว็บแอป

ในส่วนนี้ของโค้ดแล็บ คุณจะใช้การค้นหาที่กําหนดไว้ในส่วนก่อนหน้าในเว็บแอปของคุณ โปรแกรมจําลอง Firebase Data Connect จะสร้าง SDK ตามข้อมูลในไฟล์ .gql (โดยเฉพาะ schema.gql, queries.gql, mutations.gql) และไฟล์ connector.yaml คุณเรียกใช้ SDK เหล่านี้ได้โดยตรงในแอปพลิเคชัน

  1. ใน MovieService (app/src/lib/MovieService.tsx) ให้ยกเลิกการคอมเมนต์คำสั่งการนําเข้าที่ด้านบน
    import { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect";
    
    ฟังก์ชัน listMovies, ประเภทคำตอบ ListMoviesData และ enum OrderDirection คือ SDK ทั้งหมดที่โปรแกรมจำลอง Firebase Data Connect สร้างขึ้นตามสคีมาและการค้นหาที่คุณกำหนดไว้ก่อนหน้านี้
  2. แทนที่ฟังก์ชัน 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. แสดงรายละเอียดภาพยนตร์และนักแสดง

ในส่วนนี้ คุณจะใช้ฟังก์ชันการทำงานเพื่อดึงข้อมูลโดยละเอียดของภาพยนตร์หรือนักแสดงโดยใช้รหัสที่ไม่ซ้ำกัน ซึ่งไม่เพียงแต่จะดึงข้อมูลจากตารางที่เกี่ยวข้องเท่านั้น แต่ยังรวมตารางที่เกี่ยวข้องเพื่อแสดงรายละเอียดที่ครอบคลุม เช่น รีวิวภาพยนตร์และผลงานภาพยนตร์ของนักแสดง

ac7fefa7ff779231.png

ติดตั้งใช้งานเครื่องมือเชื่อมต่อ

  1. เปิด dataconnect/movie-connector/queries.gql ในโปรเจ็กต์
  2. เพิ่มข้อความค้นหาต่อไปนี้เพื่อดึงรายละเอียดภาพยนตร์และนักแสดง
    # 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
        }
      }
    }
    
  3. บันทึกการเปลี่ยนแปลงและตรวจสอบข้อความค้นหา

สรุปประเด็นสำคัญ:

  • movie()/actor(): ช่องการค้นหา GraphQL สำหรับการดึงข้อมูลภาพยนตร์หรือนักแสดงรายการเดียวจากตาราง Movies หรือ Actors
  • _on_: ตัวเลือกนี้ช่วยให้เข้าถึงฟิลด์จากประเภทที่เชื่อมโยงซึ่งมีความสัมพันธ์ของคีย์ต่างประเทศได้โดยตรง เช่น reviews_on_movie จะดึงข้อมูลรีวิวทั้งหมดที่เกี่ยวข้องกับภาพยนตร์หนึ่งๆ
  • _via_: ใช้เพื่อไปยังส่วนต่างๆ ของความสัมพันธ์แบบหลายต่อหลายรายการผ่านตารางการรวม เช่น actors_via_MovieActor เข้าถึงประเภท Actor ผ่านตารางการเข้าร่วม MovieActor และเงื่อนไข where จะกรองนักแสดงตามบทบาท (เช่น "หลัก" หรือ "สนับสนุน")

ทดสอบการค้นหาโดยป้อนข้อมูลจำลอง

  1. ในแผงการดําเนินการของ Data Connect คุณสามารถทดสอบการค้นหาได้โดยป้อนรหัสจำลอง เช่น
    {"id": "550e8400-e29b-41d4-a716-446655440000"}
    
  2. คลิกเรียกใช้ (ในเครื่อง) สำหรับ GetMovieById เพื่อเรียกข้อมูลเกี่ยวกับ "Quantum Paradox" (ภาพยนตร์จำลองที่รหัสข้างต้นเกี่ยวข้อง)

1b08961891e44da2.png

ผสานรวมการค้นหาในเว็บแอป

  1. ใน MovieService (app/src/lib/MovieService.tsx) ให้ยกเลิกการคอมเมนต์การนําเข้าต่อไปนี้
    import { getMovieById, GetMovieByIdData } from "@movie/dataconnect";
    import { GetActorByIdData, getActorById } from "@movie/dataconnect";
    
  2. แทนที่ฟังก์ชัน 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 โดยตรงได้ ซึ่งช่วยให้มั่นใจได้ว่าการจัดการผู้ใช้ภายในแอปจะปลอดภัย

9890838045d5a00e.png

ติดตั้งใช้งานเครื่องมือเชื่อมต่อ

  1. เปิด mutations.gql ใน dataconnect/movie-connector/
  2. เพิ่มการดัดแปลงต่อไปนี้เพื่อสร้างหรืออัปเดตผู้ใช้ที่ตรวจสอบสิทธิ์ในปัจจุบัน
    # 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 โดยตรง ไม่ใช่จากผู้ใช้หรือแอป ซึ่งจะเพิ่มความปลอดภัยอีกชั้นโดยการจัดการรหัสผู้ใช้อย่างปลอดภัยและอัตโนมัติ

ดึงข้อมูลผู้ใช้ปัจจุบัน

  1. เปิด queries.gql ใน dataconnect/movie-connector/
  2. เพิ่มข้อความค้นหาต่อไปนี้เพื่อดึงข้อมูลผู้ใช้ปัจจุบัน
    # 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

ผสานรวมการค้นหาในเว็บแอป

  1. ใน MovieService (app/src/lib/MovieService.tsx) ให้ยกเลิกการคอมเมนต์การนําเข้าต่อไปนี้
    import { upsertUser } from "@movie/dataconnect";
    import { getCurrentUser, GetCurrentUserData } from "@movie/dataconnect";
    
  2. แทนที่ฟังก์ชัน 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 หลังจากลงชื่อเข้าใช้แล้ว ให้คลิก "โปรไฟล์ของฉัน" ขณะนี้ส่วนนี้จะว่างเปล่า แต่คุณได้สร้างรากฐานสําหรับการจัดการข้อมูลที่เจาะจงผู้ใช้ในแอปแล้ว

8. ใช้การโต้ตอบของผู้ใช้

ในส่วนนี้ของโค้ดแล็บ คุณจะใช้การโต้ตอบของผู้ใช้ในแอปรีวิวภาพยนตร์ โดยเฉพาะอย่างยิ่งการอนุญาตให้ผู้ใช้จัดการภาพยนตร์ที่ชอบ รวมถึงเขียนหรือลบรีวิว

b3d0ac1e181c9de9.png

อนุญาตให้ผู้ใช้ตั้งค่าภาพยนตร์เป็นรายการโปรด

ในส่วนนี้ คุณจะต้องตั้งค่าฐานข้อมูลเพื่อให้ผู้ใช้เพิ่มภาพยนตร์ที่ชอบได้

ติดตั้งใช้งานเครื่องมือเชื่อมต่อ

  1. เปิด mutations.gql ใน dataconnect/movie-connector/
  2. เพิ่มการกลายพันธุ์ต่อไปนี้เพื่อจัดการกับการทำให้ภาพยนตร์เป็นรายการโปรด
    # 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 จัดหาให้โดยตรง เพื่อให้มั่นใจว่าจะมีเพียงข้อมูลของผู้ใช้ที่ตรวจสอบสิทธิ์เท่านั้นที่เข้าถึงหรือแก้ไขได้

ตรวจสอบว่าภาพยนตร์เป็นรายการโปรดหรือไม่

  1. เปิด queries.gql ใน dataconnect/movie-connector/
  2. เพิ่มการค้นหาต่อไปนี้เพื่อตรวจสอบว่าภาพยนตร์เป็นรายการโปรดหรือไม่
    query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
      favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
        movieId
      }
    }
    

สรุปประเด็นสำคัญ:

  • auth.uid: ช่วยให้เข้าถึงข้อมูลที่เจาะจงผู้ใช้ได้อย่างปลอดภัยโดยใช้การตรวจสอบสิทธิ์ Firebase
  • favorite_movie: ตรวจสอบตารางการเข้าร่วม favorite_movies เพื่อดูว่าผู้ใช้ปัจจุบันได้ทำเครื่องหมายภาพยนตร์ที่เฉพาะเจาะจงว่าเป็นรายการโปรดหรือไม่

ผสานรวมการค้นหาในเว็บแอป

  1. ใน MovieService (app/src/lib/MovieService.tsx) ให้ยกเลิกการคอมเมนต์การนําเข้าต่อไปนี้
    import { addFavoritedMovie, deleteFavoritedMovie, getIfFavoritedMovie } from "@movie/dataconnect";
    
  2. แทนที่ฟังก์ชัน 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 จึงไม่จำเป็นต้องป้อนข้อมูลด้วยตนเอง

ผสานรวมการค้นหาในเว็บแอป

  1. ใน MovieService (app/src/lib/MovieService.tsx) ให้ยกเลิกการคอมเมนต์การนําเข้าต่อไปนี้
    import { addReview, deleteReview } from "@movie/dataconnect";
    
  2. แทนที่ฟังก์ชัน 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 เพื่อนำรีวิวภาพยนตร์ของผู้ใช้ที่ตรวจสอบสิทธิ์ออก

ดูการใช้งานจริง

ตอนนี้ผู้ใช้สามารถเขียนรีวิวภาพยนตร์ในหน้ารายละเอียดภาพยนตร์ได้แล้ว นอกจากนี้ ผู้ใช้ยังดูและลบรีวิวของตนเองในหน้าโปรไฟล์ได้ด้วย ซึ่งช่วยให้ผู้ใช้ควบคุมการโต้ตอบกับแอปได้อย่างเต็มรูปแบบ

9. ตัวกรองขั้นสูงและการจับคู่ข้อความบางส่วน

ในส่วนนี้ คุณจะใช้ความสามารถในการค้นหาขั้นสูง ซึ่งช่วยให้ผู้ใช้ค้นหาภาพยนตร์ตามการจัดประเภทและปีที่เผยแพร่ที่หลากหลาย กรองตามประเภทและแท็ก ทำการจับคู่ข้อความบางส่วนในชื่อหรือคำอธิบาย และแม้แต่รวมตัวกรองหลายรายการเข้าด้วยกันเพื่อให้ได้ผลลัพธ์ที่แม่นยำยิ่งขึ้น

ece70ee0ab964e28.png

ติดตั้งใช้งานเครื่องมือเชื่อมต่อ

  1. เปิด queries.gql ใน dataconnect/movie-connector/
  2. เพิ่มข้อความค้นหาต่อไปนี้เพื่อรองรับความสามารถในการค้นหาที่หลากหลาย
    # 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 เพื่อกำหนดเกณฑ์ที่เฉพาะเจาะจงสำหรับการค้นหา

ผสานรวมการค้นหาในเว็บแอป

  1. ใน MovieService (app/src/lib/MovieService.tsx) ให้ยกเลิกการคอมเมนต์การนําเข้าต่อไปนี้
    import { searchAll, SearchAllData } from "@movie/dataconnect";
    
  2. แทนที่ฟังก์ชัน 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. ไม่บังคับ: ติดตั้งใช้งานในระบบคลาวด์ (ต้องมีการเรียกเก็บเงิน)

เมื่อคุณทําซ้ำการพัฒนาซอฟต์แวร์ภายในแล้ว ก็ถึงเวลาที่จะติดตั้งสคีมา ข้อมูล และการค้นหาลงในเซิร์ฟเวอร์ ซึ่งทําได้โดยใช้ส่วนขยาย Firebase Data Connect ใน VS Code หรือ Firebase CLI

อัปเกรดแพ็กเกจราคาของ Firebase

หากต้องการผสานรวม Firebase Data Connect กับ Cloud SQL สําหรับ PostgreSQL โปรเจ็กต์ Firebase ของคุณต้องใช้แพ็กเกจราคาแบบชําระเงินตามการใช้งาน (Blaze) ซึ่งหมายความว่าโปรเจ็กต์จะลิงก์กับบัญชีการเรียกเก็บเงินระบบคลาวด์

หากต้องการอัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze ให้ทำตามขั้นตอนต่อไปนี้

  1. ในคอนโซล Firebase ให้เลือกอัปเกรดแพ็กเกจ
  2. เลือกแพ็กเกจ Blaze ทำตามวิธีการบนหน้าจอเพื่อลิงก์บัญชีสำหรับการเรียกเก็บเงินใน Cloud กับโปรเจ็กต์
    หากจำเป็นต้องสร้างบัญชีสำหรับการเรียกเก็บเงินใน Cloud เป็นส่วนหนึ่งของการอัปเกรดนี้ คุณอาจต้องกลับไปที่ขั้นตอนการอัปเกรดในคอนโซล Firebase เพื่อดำเนินการอัปเกรดให้เสร็จสมบูรณ์

เชื่อมต่อเว็บแอปกับโปรเจ็กต์ Firebase

  1. ลงทะเบียนเว็บแอปในโปรเจ็กต์ Firebase โดยใช้คอนโซล Firebase
    1. เปิดโปรเจ็กต์ แล้วคลิกเพิ่มแอป
    2. ละเว้นการตั้งค่า SDK และการกำหนดค่าในตอนนี้ แต่อย่าลืมคัดลอกออบเจ็กต์ firebaseConfig ที่สร้างขึ้น
    7030822793e4d75b.png
  2. แทนที่ 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"
    };
    
  3. สร้างเว็บแอป: กลับไปที่ VS Code ในโฟลเดอร์ app ให้ใช้ Vite เพื่อสร้างเว็บแอปสําหรับการโฮสต์การนําส่ง ดังนี้
    cd app
    npm run build
    

ตั้งค่าการตรวจสอบสิทธิ์ Firebase ในโปรเจ็กต์ Firebase

  1. ตั้งค่าการตรวจสอบสิทธิ์ Firebase ด้วย Google Sign-In62af2f225e790ef6.png
  2. (ไม่บังคับ) อนุญาตโดเมนสําหรับการตรวจสอบสิทธิ์ Firebase โดยใช้คอนโซล Firebase (เช่น http://127.0.0.1)
    1. ในการตั้งค่าการตรวจสอบสิทธิ์ ให้ไปที่โดเมนที่ได้รับอนุญาต
    2. คลิก "เพิ่มโดเมน" และใส่โดเมนในเครื่องของคุณไว้ในรายการ

c255098f12549886.png

ทำให้ใช้งานได้ด้วย Firebase CLI

  1. ใน 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"]
    
  2. ตรวจสอบว่าคุณได้ตั้งค่า Firebase CLI กับโปรเจ็กต์แล้ว โดยทำดังนี้
    npm i -g firebase-tools
    firebase login --reauth
    firebase use --add
    
  3. ในเทอร์มินัล ให้เรียกใช้คําสั่งต่อไปนี้เพื่อทำให้ใช้งานได้
    firebase deploy --only dataconnect,hosting
    
  4. ใช้คําสั่งนี้เพื่อเปรียบเทียบการเปลี่ยนแปลงสคีมา
    firebase dataconnect:sql:diff
    
  5. หากยอมรับการเปลี่ยนแปลงได้ ให้ใช้การเปลี่ยนแปลงดังกล่าวโดยทำดังนี้
    firebase dataconnect:sql:migrate
    

อินสแตนซ์ Cloud SQL for PostgreSQL จะอัปเดตด้วยสคีมาและข้อมูลที่ติดตั้งใช้งานแล้วในขั้นสุดท้าย คุณสามารถตรวจสอบสถานะได้ในคอนโซล Firebase

ตอนนี้คุณควรเห็นแอปของคุณเผยแพร่อยู่ที่ your-project.web.app/ นอกจากนี้ คุณยังคลิกเรียกใช้ (เวอร์ชันที่ใช้งานจริง) ในแผง Firebase Data Connect ได้ เช่นเดียวกับที่ทำกับโปรแกรมจำลองในเครื่อง เพื่อเพิ่มข้อมูลลงในสภาพแวดล้อมเวอร์ชันที่ใช้งานจริง

11. ไม่บังคับ: การค้นหาเวกเตอร์ด้วย Firebase Data Connect (ต้องมีการเรียกเก็บเงิน)

ในส่วนนี้ คุณจะเปิดใช้การค้นหาเวกเตอร์ในแอปรีวิวภาพยนตร์โดยใช้ Firebase Data Connect ฟีเจอร์นี้ช่วยให้ค้นหาตามเนื้อหาได้ เช่น ค้นหาภาพยนตร์ที่มีคำอธิบายคล้ายกันโดยใช้การฝังเวกเตอร์

ขั้นตอนนี้กำหนดให้คุณทำขั้นตอนสุดท้ายของโค้ดแล็บนี้ให้เสร็จสมบูรณ์เพื่อนำไปใช้งานใน Google Cloud

4b5aca5a447d2feb.png

อัปเดตสคีมาให้รวมการฝังสําหรับช่อง

ใน 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

  1. ทำตามคำแนะนำเบื้องต้นเพื่อตั้งค่า Vertex AI API จาก Google Cloud ขั้นตอนนี้เป็นขั้นตอนสําคัญในการสนับสนุนฟังก์ชันการสร้างการฝังและเวกเตอร์การค้นหา
  2. ทำให้สคีมาใช้งานได้อีกครั้งเพื่อเปิดใช้งาน pgvector และการค้นหาเวกเตอร์โดยคลิก "ทำให้ใช้งานได้จริง" โดยใช้ส่วนขยาย Firebase Data Connect ใน VS Code

ป้อนข้อมูลฐานข้อมูลด้วยข้อมูลเชิงลึก

  1. เปิดโฟลเดอร์ dataconnect ใน VS Code
  2. คลิกเรียกใช้(ในเครื่อง) ใน optional_vector_embed.gql เพื่อป้อนข้อมูลฐานข้อมูลด้วยข้อมูลเชิงลึกของภาพยนตร์

b858da780f6ec103.png

เพิ่มคำค้นหาเวกเตอร์

ใน 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 รายการ

ใช้ฟังก์ชันการค้นหาเวกเตอร์ในแอป

เมื่อตั้งค่าสคีมาและคําค้นหาแล้ว ให้ผสานรวมการค้นหาเวกเตอร์เข้ากับเลเยอร์บริการของแอป ขั้นตอนนี้ช่วยให้คุณเรียกใช้คำค้นหาจากเว็บแอปได้

  1. ใน app/src/lib/ MovieService.ts ให้ยกเลิกการคอมเมนต์การนําเข้าต่อไปนี้จาก SDK ซึ่งจะทํางานเหมือนกับการค้นหาอื่นๆ
    import {
      searchMovieDescriptionUsingL2similarity,
      SearchMovieDescriptionUsingL2similarityData,
    } from "@movie/dataconnect";
    
  2. เพิ่มฟังก์ชันต่อไปนี้เพื่อผสานรวมการค้นหาที่อิงตามเวกเตอร์ไว้ในแอป
    // 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 โดยส่งข้อความที่ป้อนเพื่อค้นหาเนื้อหาตามเวกเตอร์

ดูการใช้งานจริง

ไปที่ส่วน "การค้นหาเวกเตอร์" ในแถบนําทาง แล้วพิมพ์วลีอย่าง "โรแมนติกและทันสมัย" คุณจะเห็นรายการภาพยนตร์ที่ตรงกับเนื้อหาที่คุณค้นหา หรือไปที่หน้ารายละเอียดภาพยนตร์ของภาพยนตร์เรื่องใดก็ได้ แล้วดูส่วนภาพยนตร์ที่คล้ายกันซึ่งอยู่ด้านล่างของหน้า

7b71f1c75633c1be.png

12. บทสรุป

ยินดีด้วย คุณควรใช้เว็บแอปได้แล้ว หากต้องการเล่นกับข้อมูลภาพยนตร์ของคุณเอง ไม่ต้องกังวล เพียงแทรกข้อมูลของคุณเองโดยใช้ส่วนขยาย Firebase Data Connect โดยเลียนแบบไฟล์ _insert.gql หรือเพิ่มผ่านแผงการดำเนินการของ Data Connect ใน VS Code

ดูข้อมูลเพิ่มเติม