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

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

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

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

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

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

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

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

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

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

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

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

  • @table(name) และ @col(name) เพื่อปรับแต่งชื่อตารางและชื่อคอลัมน์ SQL SQL 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)")
}

สเกลาร์หลักและค่าเซิร์ฟเวอร์

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

สเกลาร์หลัก คือตัวระบุออบเจ็กต์ที่กระชับซึ่ง SQL 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 ในตารางที่มีข้อจำกัดคีย์นอก SQL Connect จะสร้างฟิลด์ที่เกี่ยวข้องใน อีกด้านหนึ่งโดยอัตโนมัติ คุณไม่จำเป็นต้องกำหนดฟิลด์การแมปย้อนกลับ (เช่น จาก Actor กลับไปที่ MovieActor)

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

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

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

  • @ref(fields) จะระบุฟิลด์คีย์นอกที่จะใช้
  • @ref(references) จะระบุฟิลด์ที่อ้างอิงในตารางเป้าหมาย (ค่าเริ่มต้นคือคีย์หลัก แต่ฟิลด์ @unique ก็ใช้ได้เช่นกัน) นี่เป็นตัวเลือกขั้นสูง SQL 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
}

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

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

สมมติว่าสคีมามีประเภท Movie และประเภท Actor ที่เชื่อมโยงกัน SQL 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 }
    }
  }

เมื่อทราบข้อมูลนี้แล้ว คุณสามารถอ่านวิธีใช้การดำเนินการโดยใช้ฟิลด์เหล่านี้ ได้ในคู่มือการใช้การค้นหาและ คู่มือการใช้การเปลี่ยนแปลง

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

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

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

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

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 เราได้เพิ่มฟิลด์การแจงนับ originalAspectRatio สำหรับสัดส่วนภาพที่ใช้ถ่ายทำภาพยนตร์ และฟิลด์ otherAspectRatios อีกฟิลด์หนึ่งสำหรับรายการสัดส่วนภาพอื่นๆ ที่มี

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

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

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

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

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

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

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

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

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

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

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

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

timestamptz

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

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

enum

Vector กำหนดเอง vector

vector

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

  • List ของ GraphQL จะแมปกับอาร์เรย์ 1 มิติ
    • เช่น [Int] จะแมปกับ int5[] และ [Any] จะแมปกับ jsonb[]
    • SQL 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);

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

คุณอาจสนใจหัวข้อต่อไปนี้