ออกแบบสคีมา Data Connect

เมื่อใช้ Firebase Data Connect คุณจะออกแบบสคีมา GraphQL ที่แสดง โมเดลข้อมูลที่แอปพลิเคชันต้องการ Data Connect จะแปลง สคีมานี้เป็นอินสแตนซ์ Cloud SQL สำหรับ PostgreSQL ที่สนับสนุนแอปของคุณ จากนั้นคุณ จะเขียนการค้นหาและการเปลี่ยนแปลงเพื่อเชื่อมต่อกับแบ็กเอนด์และรวม การดำเนินการเหล่านี้ไว้ในเครื่องมือเชื่อมต่อเพื่อใช้ข้อมูลจากโค้ดฝั่งไคลเอ็นต์

Data Connect มีเครื่องมือ AI ที่จะช่วยคุณออกแบบและใช้ สคีมา คู่มือนี้จะแนะนำแนวคิดสำคัญในการออกแบบสคีมาเพื่อรองรับ และเสริมเวิร์กโฟลว์มาตรฐานและเวิร์กโฟลว์ที่ AI ช่วยเมื่อคุณเริ่มพัฒนาแอปและหลังจากนั้น

คู่มือการเริ่มต้นใช้งานได้แนะนำสคีมาแอปรีวิวภาพยนตร์สำหรับ PostgreSQL

คู่มือนี้จะพัฒนาสคีมาดังกล่าวต่อไปและแสดงข้อมูล SQL ที่เทียบเท่ากับสคีมาแอปรีวิวภาพยนตร์ขั้นสุดท้าย

สคีมาสำหรับแอปรีวิวภาพยนตร์

สมมติว่าคุณต้องการสร้างบริการที่ให้ผู้ใช้ส่งและดูรีวิวภาพยนตร์

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

ใน Data Connect คุณจะกําหนดประเภท GraphQL เพื่อกําหนดรูปร่างของ ข้อมูลที่ไคลเอ็นต์สามารถค้นหาและจัดการได้ เมื่อเขียนสคีมา ระบบจะแปลประเภทของคุณเป็นตาราง Cloud SQL สำหรับ PostgreSQL ซึ่งส่วนใหญ่จะอยู่ในความสัมพันธ์โดยตรงระหว่างประเภท GraphQL กับตารางฐานข้อมูล แม้ว่าการแมปอื่นๆ จะเป็นไปได้ก็ตาม คู่มือนี้แสดงตัวอย่างตั้งแต่ระดับพื้นฐานไปจนถึงระดับสูง

กำหนดประเภท Movie พื้นฐาน

คุณเริ่มต้นด้วยประเภท Movie ได้

สคีมาสำหรับ Movie มีคำสั่งหลักๆ เช่น

  • @table(name) และ @col(name) เพื่อปรับแต่งชื่อตารางและคอลัมน์ SQL Data Connect จะสร้างชื่อในรูปแบบ snake_case หากไม่ได้ระบุ
  • @col(dataType) เพื่อปรับแต่งประเภทคอลัมน์ SQL
  • @default เพื่อกำหนดค่าเริ่มต้นของคอลัมน์ SQL ในระหว่างการแทรก

ดูรายละเอียดเพิ่มเติมได้ที่เอกสารอ้างอิงสำหรับ @table, @col, @default

# Movies
type Movie @table(name: "movie", key: "id") {
  id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
  title: String!
  releaseYear: Int
  genre: String @col(dataType: "varchar(20)")
  rating: Int
  description: String
}

จัดเก็บข้อมูลผู้ใช้ที่สำคัญโดยอัตโนมัติในUserประเภท

แอปของคุณจะติดตามผู้ใช้ ดังนั้นคุณจึงต้องมีUserประเภท

โดยเฉพาะอย่างยิ่งในกรณีนี้ คำสั่ง @default จะมีประโยชน์อย่างมาก ฟิลด์ id ที่นี่ สามารถดึงรหัสของผู้ใช้จากการตรวจสอบสิทธิ์ได้โดยอัตโนมัติ โปรดสังเกต การใช้ @default(expr: "auth.uid") ในตัวอย่างต่อไปนี้

# Users
# Suppose a user can leave reviews for movies
type User @table {
  id: String! @default(expr: "auth.uid")
  username: String! @col(dataType: "varchar(50)")
}

สเกลาร์และค่าเซิร์ฟเวอร์ที่สำคัญ

ก่อนที่จะดูแอปรีวิวภาพยนตร์เพิ่มเติม สิ่งสำคัญคือต้อง แนะนำData Connect สเกลาร์หลักและค่าเซิร์ฟเวอร์

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

การใช้ค่าเซิร์ฟเวอร์ช่วยให้เซิร์ฟเวอร์สามารถป้อนข้อมูลแบบไดนามิกลงในช่องต่างๆ ในตารางได้โดยใช้ค่าที่จัดเก็บไว้หรือค่าที่คำนวณได้ตาม นิพจน์ CEL ฝั่งเซิร์ฟเวอร์ที่เฉพาะเจาะจงในอาร์กิวเมนต์ expr เช่น คุณ สามารถกำหนดฟิลด์ที่มีการประทับเวลาเมื่อเข้าถึงฟิลด์โดยใช้ เวลาที่จัดเก็บไว้ในคำขอการดำเนินการ updatedAt: Timestamp! @default(expr: "request.time")

จัดการความสัมพันธ์แบบหลายต่อหลายในประเภท Actor และ MovieActor

เมื่อจัดการผู้ใช้แล้ว คุณจะกลับไปสร้างโมเดลข้อมูลภาพยนตร์ได้

จากนั้นคุณก็อยากให้นักแสดงมาแสดงในภาพยนตร์ของคุณ

ตาราง Actor นั้นค่อนข้างตรงไปตรงมา

# Actors
# Suppose an actor can participate in multiple movies and movies can have multiple actors
# Movie - Actors (or vice versa) is a many to many relationship
type Actor @table {
  id: UUID! @default(expr: "uuidV4()")
  name: String! @col(dataType: "varchar(30)")
}

หากต้องการให้นักแสดงปรากฏในภาพยนตร์หลายเรื่องและให้ภาพยนตร์มีนักแสดงหลายคน คุณจะต้องมี "ตารางรวม"

ตาราง MovieActor จัดการความสัมพันธ์แบบหลายต่อหลาย และคีย์หลักของตารางคือการรวมกันของ [movie, actor] (ฟิลด์คีย์นอกจาก movie และ actor)

# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary keys of this table
# In this case, the keys are [movieId, actorId], the foreign key fields of the reference fields [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
  movie: Movie!
  # movieId: UUID! <- implicitly added foreign key field
  actor: Actor!
  # actorId: UUID! <- implicitly added foreign key field
  role: String! # "main" or "supporting"
  # optional other fields
}

เมื่อคุณกําหนดความสัมพันธ์ SQL ในตารางที่มีข้อจํากัดคีย์นอก Data Connect จะสร้างฟิลด์ที่สอดคล้องกันในอีกด้านหนึ่งโดยอัตโนมัติ คุณไม่จำเป็นต้องกำหนดฟิลด์การแมปย้อนกลับ (เช่น จาก Actor กลับไปที่ MovieActor)

จัดการความสัมพันธ์แบบหนึ่งต่อหนึ่งในประเภท MovieMetadata

ตอนนี้คุณสามารถติดตามผู้กำกับภาพยนตร์ รวมถึงตั้งค่าความสัมพันธ์แบบหนึ่งต่อหนึ่ง กับ Movie ได้แล้ว

คุณใช้คำสั่ง @ref เพื่อปรับแต่งข้อจํากัดของคีย์นอกได้ดังนี้

  • @ref(fields) ระบุฟิลด์คีย์นอกที่จะใช้
  • @ref(references) ระบุฟิลด์ที่อ้างอิงในตารางเป้าหมาย (ค่าเริ่มต้นคือคีย์หลัก แต่ฟิลด์ @unique ก็ใช้ได้เช่นกัน) นี่เป็นตัวเลือกที่ ซับซ้อนกว่า Data Connect มักจะอนุมานให้คุณได้

ดูรายละเอียดเพิ่มเติมได้ที่เอกสารอ้างอิงสำหรับ @ref

# Movie Metadata
# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique ensures that each Movie only has one MovieMetadata.
  movie: Movie! @unique
  # Since it references to another table type, it adds a foreign key constraint.
  #  movie: Movie! @unique @ref(fields: "movieId", references: "id")
  #  movieId: UUID! <- implicitly added foreign key field
  director: String
}

ใช้ฟิลด์ที่สร้างจากสคีมาเพื่อสร้างการดำเนินการ

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

สมมติว่าสคีมามีประเภท Movie และประเภท Actor ที่เชื่อมโยงกัน Data Connect จะสร้างช่อง movie, movies, actors_on_movies และอื่นๆ

ค้นหาด้วยฟิลด์
movie

ฟิลด์ movie แสดงระเบียนเดียวในตาราง Movie

ใช้ฟิลด์นี้เพื่อค้นหาภาพยนตร์เรื่องเดียวตามคีย์

query GetMovie($myKey: Movie_Key!) {
  movie(key: $myKey) { title }
}

ค้นหาด้วยฟิลด์
movies

ฟิลด์ movies แสดงรายการระเบียนในตาราง Movie

ใช้ช่องนี้เพื่อค้นหาภาพยนตร์หลายเรื่อง เช่น ภาพยนตร์ทั้งหมด ที่ออกฉายในปีที่กำหนด

query GetMovies($myYear: Int!) {
  movies(where: { year: { eq: $myYear } }) { title }
}

ค้นหาด้วยฟิลด์
actors_on_movies

ฟิลด์ actors_on_movies แสดงรายการระเบียนที่เชื่อมต่อตาราง Actor และ Movie ใช้ฟิลด์นี้เพื่อค้นหานักแสดงทั้งหมดที่เกี่ยวข้องกับภาพยนตร์ที่กำหนด

ใช้ฟิลด์นี้เพื่อค้นหานักแสดงทั้งหมดที่เกี่ยวข้องกับภาพยนตร์ที่กำหนด

  query GetActorsOnMovie($myKey: Movie_Key!) {
    actors_on_movies(where: { movie: { key: { eq: $myKey } } }) {
      actor { name }
    }
  }

ด้วยเหตุนี้ คุณจึงอ่านวิธีใช้ช่องเหล่านี้เพื่อดำเนินการได้ ในคำแนะนำในการใช้การค้นหาและ คำแนะนำในการใช้การเปลี่ยนแปลง

แนวคิดสคีมาขั้นสูงเพิ่มเติม

ฟิลด์การแจงนับ

Data Connect รองรับฟิลด์การแจงนับที่แมปกับประเภทการแจงนับของ PostgreSQL Enums ช่วยให้คุณกำหนดรายการค่าแบบคงที่ที่กำหนดไว้ล่วงหน้าได้อย่างรวดเร็ว โดยมีลำดับที่เฉพาะเจาะจง

หากต้องการเพิ่ม Enum ลงในสคีมา ให้ประกาศ Enum และค่าที่กำหนดไว้ล่วงหน้า จากนั้นอ้างอิงในประเภท

enum AspectRatio {
   ACADEMY
   WIDESCREEN
   ANAMORPHIC
   IMAX
   "No information available on aspect ratio"
   UNAVAILABLE
}

type Movie
  @table {
  title: String! 
  genre: String
  description: String
  originalAspectRatio: AspectRatio! @default(value: WIDESCREEN)
  otherAspectRatios: [AspectRatio!]
  tags: [String]
  rating: Float
  imageUrl: String!
  releaseYear: Int
}

ในMovieประเภท เราได้เพิ่มฟิลด์ Enum originalAspectRatio สำหรับสัดส่วน ภาพที่ใช้ถ่ายทำภาพยนตร์ และฟิลด์อีกรายการ otherAspectRatios สำหรับ รายการสัดส่วนภาพอื่นๆ ที่พร้อมใช้งาน

จัดการการเปลี่ยนแปลงในฟิลด์การแจงนับ

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

คุณไม่ควรจัดลำดับค่าในรายการค่า Enum ใหม่ เนื่องจากลำดับมีความสำคัญเพราะจะเปลี่ยนวิธีใช้การกรอง

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

การใช้ฟิลด์ enum ในการดำเนินการและในโค้ดฝั่งไคลเอ็นต์

ตอนนี้คุณได้เพิ่มฟิลด์ Enum ลงในสคีมาแล้ว คุณสามารถใช้ฟิลด์นี้ใน การค้นหาและโค้ดฝั่งไคลเอ็นต์ได้

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเขียนการค้นหาโดยใช้ Enum และวิธีเขียนไคลเอ็นต์เพื่ออนุญาตให้ปรับ Enum ได้โดยเริ่มจากคำแนะนำในการค้นหา

แนวคิดขั้นสูงอื่นๆ

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

ประเภทข้อมูลที่รองรับ

Data Connect รองรับประเภทข้อมูลสเกลาร์ต่อไปนี้ โดยมีการกำหนดประเภท PostgreSQL โดยใช้ @col(dataType:)

Data Connect ประเภท ประเภทในตัวของ GraphQL หรือ
Data Connect ประเภทที่กำหนดเอง
ประเภท PostgreSQL เริ่มต้น ประเภท PostgreSQL ที่รองรับ
(ชื่อแทนในวงเล็บ)
สตริง GraphQL ข้อความ text
bit(n), varbit(n)
char(n), varchar(n)
Int GraphQL int Int2 (smallint, smallserial),
int4 (integer, int, serial)
ทศนิยม GraphQL float8 float4 (real)
float8 (double precision)
numeric (decimal)
บูลีน GraphQL boolean boolean
UUID กำหนดเอง uuid uuid
Int64 กำหนดเอง bigint int8 (bigint, bigserial)
numeric (decimal)
วันที่ กำหนดเอง วันที่ วันที่
การประทับเวลา กำหนดเอง timestamptz

timestamptz

หมายเหตุ: ระบบจะไม่จัดเก็บข้อมูลเขตเวลาท้องถิ่น
PostgreSQL จะแปลงและจัดเก็บการประทับเวลาดังกล่าวเป็น UTC

การแจงนับ กำหนดเอง enum

enum

Vector กำหนดเอง vector

เวกเตอร์

ดูค้นหาความคล้ายกันของเวกเตอร์ด้วย Vertex AI

  • GraphQL List จะแมปกับอาร์เรย์แบบมิติเดียว
    • เช่น [Int] แมปกับ int5[], [Any] แมปกับ jsonb[]
    • Data Connect ไม่รองรับอาร์เรย์แบบซ้อน

สคีมา SQL ที่เทียบเท่า

-- Movies Table
CREATE TABLE Movies (
    movie_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    release_year INT,
    genre VARCHAR(30),
    rating INT,
    description TEXT,
    tags TEXT[]
);
-- Movie Metadata Table
CREATE TABLE MovieMetadata (
    movie_id UUID REFERENCES Movies(movie_id) UNIQUE,
    director VARCHAR(255) NOT NULL,
    PRIMARY KEY (movie_id)
);
-- Actors Table
CREATE TABLE Actors (
    actor_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    name VARCHAR(30) NOT NULL
);
-- MovieActor Join Table for Many-to-Many Relationship
CREATE TABLE MovieActor (
    movie_id UUID REFERENCES Movies(movie_id),
    actor_id UUID REFERENCES Actors(actor_id),
    role VARCHAR(50) NOT NULL, # "main" or "supporting"
    PRIMARY KEY (movie_id, actor_id),
    FOREIGN KEY (movie_id) REFERENCES Movies(movie_id),
    FOREIGN KEY (actor_id) REFERENCES Actors(actor_id)
);
-- Users Table
CREATE TABLE Users (
    user_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    user_auth VARCHAR(255) NOT NULL
    username VARCHAR(30) NOT NULL
);
-- Reviews Table
CREATE TABLE Reviews (
    review_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    user_id UUID REFERENCES Users(user_id),
    movie_id UUID REFERENCES Movies(movie_id),
    rating INT,
    review_text TEXT,
    review_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE (movie_id, user_id)
    FOREIGN KEY (user_id) REFERENCES Users(user_id),
    FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
-- Self Join Example for Movie Sequel Relationship
ALTER TABLE Movies
ADD COLUMN sequel_to UUID REFERENCES Movies(movie_id);

ขั้นตอนถัดไป

คุณอาจสนใจ