สร้างด้วย 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. ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์

ในขั้นตอนนี้ของ Codelab จะแนะนําการตั้งค่าสภาพแวดล้อมเพื่อเริ่มสร้างแอปรีวิวภาพยนตร์โดยใช้ 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]
}

สิ่งสำคัญที่ได้เรียนรู้:

  • รหัส: 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. ดึงข้อมูลภาพยนตร์ยอดนิยมและล่าสุด

แอป FriendlyMovies

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

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

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

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

  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 เพื่อสร้างหรืออัปเดตข้อมูลของผู้ใช้ในฐานข้อมูล
  • 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 Authentication โดยตรง เพื่อให้มั่นใจว่าจะมีการเข้าถึงหรือแก้ไขข้อมูลของผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์เท่านั้น

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

  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: เรียกใช้ addReviewmutation เพื่อเพิ่มรีวิวสำหรับภาพยนตร์ที่ระบุ โดยลิงก์รีวิวกับผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์อย่างปลอดภัย
  • 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 clause: ระบุเงื่อนไขสำหรับการกรองข้อมูล แต่ละส่วน (ภาพยนตร์ นักแสดง รีวิว) ใช้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. ไม่บังคับ: ทำให้ใช้งานได้กับ Cloud (ต้องมีการเรียกเก็บเงิน)

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

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

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

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

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

เชื่อมต่อเว็บแอปกับโปรเจ็กต์ 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 Authentication ด้วยการลงชื่อเข้าใช้ด้วย Google62af2f225e790ef6.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 สำหรับ PostgreSQL ด้วยสคีมาและข้อมูลที่ปรับใช้ขั้นสุดท้าย คุณสามารถตรวจสอบสถานะได้ในคอนโซล Firebase

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

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

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

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

4b5aca5a447d2feb.png

อัปเดตสคีมาให้มี 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

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

ป้อนข้อมูลการฝังลงในฐานข้อมูล

  1. เปิดโฟลเดอร์ dataconnect ใน VS Code
  2. คลิก Run(local) ใน 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 โดยส่งข้อความที่ป้อนเพื่อทำการค้นหาเนื้อหาตามเวกเตอร์

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

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

7b71f1c75633c1be.png

12. บทสรุป

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

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