ใช้การเปลี่ยนแปลง SQL Connect

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

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

นอกจากนี้ คู่มือดังกล่าวยังได้แนะนำการดำเนินการดูแลระบบทั้งแบบที่ติดตั้งใช้งานได้และแบบเฉพาะกิจ ซึ่งรวมถึงการเปลี่ยนแปลง

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

คู่มือนี้จะเจาะลึกการเปลี่ยนแปลงที่ติดตั้งใช้งานได้

ฟีเจอร์ของการเปลี่ยนแปลง SQL Connect

SQL Connect ช่วยให้คุณทำการเปลี่ยนแปลงพื้นฐานได้ทุกวิธี ตามที่คุณคาดหวังจากฐานข้อมูล PostgreSQL ดังนี้

  • ดำเนินการ CRUD
  • จัดการการดำเนินการหลายขั้นตอนด้วยธุรกรรม

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

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

ใช้ฟิลด์ที่สร้างขึ้นเพื่อติดตั้งใช้งานการเปลี่ยนแปลง

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

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

สมมติว่าสคีมามีประเภท Movie และประเภท Actor ที่เชื่อมโยงกัน SQL Connect จะสร้างฟิลด์ movie_insert, movie_update, movie_delete และอื่นๆ

การเปลี่ยนแปลงด้วยฟิลด์
movie_insert

ฟิลด์ movie_insert แสดงถึงการเปลี่ยนแปลงเพื่อ สร้างระเบียนเดียวในตาราง Movie

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

mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
  movie_insert(data: {
    title: $title
    releaseYear: $releaseYear
    genre: $genre
    rating: $rating
  })
}

การเปลี่ยนแปลงด้วยฟิลด์
movie_update

ฟิลด์ movie_update แสดงถึงการเปลี่ยนแปลงเพื่อ อัปเดตระเบียนเดียวในตาราง Movie

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

mutation UpdateMovie($myKey: Movie_Key!, $genre: String, $rating: Int, $description: String) {
  movie_update(key: $myKey, data: {
    genre: $genre
    rating: $rating
    description: $description
  })
}

การเปลี่ยนแปลงด้วยฟิลด์
movie_delete

ฟิลด์ movie_delete แสดงถึงการเปลี่ยนแปลงเพื่อ ลบระเบียนเดียวในตาราง Movie

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

  mutation DeleteMovie($myKey: Movie_Key!) {
    movie_delete(key: $myKey) { key }
  }

องค์ประกอบสำคัญของการเปลี่ยนแปลง

SQL Connect การเปลี่ยนแปลงคือการเปลี่ยนแปลง GraphQL ที่มี SQL Connect ส่วนขยาย เช่นเดียวกับการเปลี่ยนแปลง GraphQL ปกติ คุณสามารถกำหนดชื่อการดำเนินการและรายการตัวแปร GraphQL ได้

SQL Connect ขยายการค้นหา GraphQL ด้วยคำสั่ง ที่กำหนดเอง เช่น @auth และ @transaction

ดังนั้นการเปลี่ยนแปลงต่อไปนี้จึงมีองค์ประกอบดังนี้

  • คำจำกัดความประเภท mutation
  • ชื่อการดำเนินการ (การเปลี่ยนแปลง) SignUp
  • อาร์กิวเมนต์การดำเนินการตัวแปรเดียว $username
  • คำสั่งเดียว @auth
  • ฟิลด์เดียว user_insert
mutation SignUp($username: String!) @auth(level: USER) {
  user_insert(data: {
    id_expr: "auth.uid"
    username: $username
  })
}

อาร์กิวเมนต์การเปลี่ยนแปลงทุกรายการต้องมีการประกาศประเภท ซึ่งอาจเป็นประเภทในตัว เช่น String หรือประเภทที่กำหนดโดยสคีมาที่กำหนดเอง เช่น Movie

เขียนการเปลี่ยนแปลงพื้นฐาน

คุณสามารถเริ่มเขียนการเปลี่ยนแปลงเพื่อสร้าง อัปเดต และลบระเบียนแต่ละรายการจากฐานข้อมูลได้

สร้าง

มาสร้างพื้นฐานกัน

# Create a movie based on user input
mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
  movie_insert(data: {
    title: $title
    releaseYear: $releaseYear
    genre: $genre
    rating: $rating
  })
}

# Create a movie with default values
mutation CreateMovie2 {
  movie_insert(data: {
    title: "Sherlock Holmes"
    releaseYear: 2009
    genre: "Mystery"
    rating: 5
  })
}

หรือ upsert

# Movie upsert using combination of variables and literals
mutation UpsertMovie($title: String!) {
  movie_upsert(data: {
    title: $title
    releaseYear: 2009
    genre: "Mystery"
    rating: 5
    genre: "Mystery/Thriller"
  })
}

ทำการอัปเดต

ตัวอย่างการอัปเดต โปรดิวเซอร์และผู้กำกับหวังว่าคะแนนเฉลี่ยเหล่านั้นจะเป็นไปตามเทรนด์

ฟิลด์ movie_update มีอาร์กิวเมนต์ id ที่คาดไว้เพื่อระบุระเบียนและฟิลด์ data ที่คุณใช้เพื่อตั้งค่าในการอัปเดตนี้ได้

mutation UpdateMovie(
  $id: UUID!,
  $genre: String!,
  $rating: Int!,
  $description: String!
) {
  movie_update(id: $id,
    data: {
      genre: $genre
      rating: $rating
      description: $description
    })
}

หากต้องการทำการอัปเดตหลายรายการ ให้ใช้ฟิลด์ movie_updateMany

# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $rating: Int!) {
  movie_updateMany(
    where: { genre: { eq: $genre } },
    data:
      {
        rating: $rating
      })
}

ใช้การดำเนินการเพิ่ม ลด ผนวก และนำหน้าด้วย _update

แม้ว่าในการเปลี่ยนแปลง _update และ _updateMany คุณจะตั้งค่าใน data: ได้อย่างชัดเจน แต่การใช้โอเปอเรเตอร์ เช่น เพิ่ม เพื่ออัปเดต ค่ามักจะสมเหตุสมผลกว่า

หากต้องการแก้ไขตัวอย่างการอัปเดตก่อนหน้านี้ ให้สมมติว่าคุณต้องการเพิ่มคะแนนของภาพยนตร์เรื่องหนึ่ง คุณสามารถใช้ไวยากรณ์ rating_update กับโอเปอเรเตอร์ inc ได้

mutation UpdateMovie(
  $id: UUID!,
  $ratingIncrement: Int!
) {
  movie_update(id: $id, data: {
    rating_update: {
      inc: $ratingIncrement
    }
  })
}

SQL Connect รองรับโอเปอเรเตอร์ต่อไปนี้สำหรับการอัปเดตฟิลด์

  • inc เพื่อเพิ่มประเภทข้อมูล Int, Int64, Float, Date และ Timestamp
  • dec เพื่อลดประเภทข้อมูล Int, Int64, Float, Date และ Timestamp

สำหรับรายการ คุณยังอัปเดตด้วยค่าแต่ละค่าหรือรายการค่าได้โดยใช้โอเปอเรเตอร์ต่อไปนี้

  • add เพื่อผนวกรายการหากรายการนั้นยังไม่ได้อยู่ในประเภทรายการ ยกเว้นรายการเวกเตอร์
  • remove เพื่อนำรายการทั้งหมดออกจากประเภทรายการ หากมี ยกเว้นรายการเวกเตอร์
  • append เพื่อผนวกรายการลงในประเภทรายการ ยกเว้นรายการเวกเตอร์
  • prepend เพื่อนำหน้ารายการลงในประเภทรายการ ยกเว้นรายการเวกเตอร์

ทำการลบ

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

# Delete by key
mutation DeleteMovie($id: UUID!) {
  movie_delete(id: $id)
}

คุณสามารถใช้ _deleteMany ได้ที่นี่

# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
  movie_deleteMany(where: { rating: { le: $minRating } })
}

เขียนการเปลี่ยนแปลงในความสัมพันธ์

ดูวิธีใช้การเปลี่ยนแปลง _upsert โดยนัยในความสัมพันธ์

# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
  movieMetadata_upsert(
    data: { movie: { id: $movieId }, director: $director }
  )
}

ออกแบบสคีมาสำหรับการเปลี่ยนแปลงที่มีประสิทธิภาพ

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

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

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

เขียนการเปลี่ยนแปลงขั้นสูง: ให้ SQL Connect ระบุค่าโดยใช้ field_expr ไวยากรณ์

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

นอกจากนี้ คุณยังใช้ข้อมูล เช่น รหัสผู้ใช้ ที่ส่งใน SQL Connect request จากแอปไคลเอ็นต์ได้ด้วย

เมื่อติดตั้งใช้งานการเปลี่ยนแปลง ให้ใช้ไวยากรณ์ field_expr เพื่อทริกเกอร์การอัปเดตที่เซิร์ฟเวอร์สร้างขึ้นหรือเข้าถึงข้อมูลจากคำขอ ตัวอย่างเช่น หากต้องการส่ง การให้สิทธิ์เข้าถึง uid ที่เก็บไว้ในคำขอไปยังการดำเนินการ _upsert ให้ส่ง "auth.uid" ในฟิลด์ userId_expr

# 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 })
}

หรือในแอปรายการสิ่งที่ต้องทำที่คุ้นเคย เมื่อสร้างรายการสิ่งที่ต้องทำใหม่ คุณสามารถส่ง id_expr เพื่อสั่งให้เซิร์ฟเวอร์สร้าง UUID สำหรับรายการโดยอัตโนมัติ

mutation CreateTodoListWithFirstItem(
  $listName: String!
) @transaction {
  # Step 1
  todoList_insert(data: {
    id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
    name: $listName,
  })
}

ดูข้อมูลเพิ่มเติมได้ที่สเกลาร์ _Expr ใน เอกสารอ้างอิงสเกลาร์

เขียนการเปลี่ยนแปลงขั้นสูง: การดำเนินการหลายขั้นตอน

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

SQL Connect ช่วยให้คุณดำเนินการตรรกะหลายขั้นตอนในการเปลี่ยนแปลงได้โดย รองรับสิ่งต่อไปนี้

  • ฟิลด์การเขียนหลายรายการ

  • ฟิลด์การอ่านหลายรายการในการเปลี่ยนแปลง (โดยใช้คีย์เวิร์ดฟิลด์ query)

  • คำสั่ง @transaction ซึ่งรองรับ ธุรกรรมที่คุ้นเคยจากฐานข้อมูลเชิงสัมพันธ์

  • คำสั่ง @check ซึ่งช่วยให้ คุณประเมินเนื้อหาของการอ่านโดยใช้นิพจน์ CEL และดำเนินการต่อไปนี้ตามผลการประเมิน

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

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

    • ในคำสั่ง @check ผ่านอาร์กิวเมนต์ expr:
    • ด้วยค่าเซิร์ฟเวอร์ โดยใช้ไวยากรณ์ field_expr

คำสั่ง @transaction

การรองรับการเปลี่ยนแปลงหลายขั้นตอนรวมถึงการจัดการข้อผิดพลาดโดยใช้ธุรกรรม

คำสั่ง @transaction บังคับให้การเปลี่ยนแปลงที่มีฟิลด์การเขียนเดียว (เช่น _insert หรือ _update) หรือมีฟิลด์การเขียนหลายรายการทำงานในธุรกรรมฐานข้อมูลเสมอ

  • การเปลี่ยนแปลงที่ไม่มี @transaction จะดำเนินการฟิลด์รูทแต่ละรายการทีละรายการตามลำดับ การดำเนินการจะแสดงข้อผิดพลาดเป็นข้อผิดพลาดของฟิลด์บางส่วน แต่จะไม่แสดงผลกระทบของการดำเนินการที่ตามมา

  • การเปลี่ยนแปลงที่มี @transaction จะสำเร็จทั้งหมดหรือล้มเหลวทั้งหมด หากฟิลด์ใดฟิลด์หนึ่งภายในธุรกรรมล้มเหลว ระบบจะย้อนกลับธุรกรรมทั้งหมด

คำสั่ง @check และ @redact

คำสั่ง @check จะยืนยันว่าฟิลด์ที่ระบุมีอยู่ในผลการค้นหา ระบบจะใช้นิพจน์ Common Expression Language (CEL) เพื่อทดสอบค่าฟิลด์ ลักษณะการทำงานเริ่มต้นของคำสั่งคือการตรวจสอบและปฏิเสธโหนดที่มีค่าเป็น null หรือ [] (รายการว่าง)

คำสั่ง @redact จะปกปิดส่วนหนึ่งของการตอบกลับจากไคลเอ็นต์ ระบบจะยังคงประเมินฟิลด์ที่ปกปิดเพื่อดูผลข้างเคียง (รวมถึงการเปลี่ยนแปลงข้อมูลและ @check) และขั้นตอนต่อๆ ไปในนิพจน์ CEL จะยังคงเข้าถึงผลลัพธ์ได้

ใช้ @check, @check(message:) และ @redact

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

query GetMovieEditors($movieId: UUID!) @auth(level: USER) {
  moviePermission(key: { movieId: $movieId, userId_expr: "auth.uid" }) @redact {
    role @check(expr: "this == 'admin'", message: "You must be an admin to view all editors of a movie.")
  }
  moviePermissions(where: { movieId: { eq: $movieId }, role: { eq: "editor" } }) {
    user {
      id
      username
    }
  }
}

หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับคำสั่ง @check และ @redact ในการตรวจสอบการให้สิทธิ์เข้าถึง โปรดดูการสนทนาเกี่ยวกับการค้นหาข้อมูลการให้สิทธิ์เข้าถึง

ใช้ @check เพื่อตรวจสอบคีย์

ฟิลด์การเปลี่ยนแปลงบางรายการ เช่น _update อาจไม่มีการดำเนินการใดๆ หากไม่มีระเบียนที่มีคีย์ที่ระบุ ในทำนองเดียวกัน การค้นหาอาจแสดงผลเป็น null หรือรายการว่าง ระบบจะไม่ถือว่าสิ่งเหล่านี้เป็นข้อผิดพลาดและจะไม่ทริกเกอร์การย้อนกลับ

หากต้องการป้องกันผลลัพธ์นี้ ให้ทดสอบว่าพบคีย์ได้หรือไม่โดยใช้คำสั่ง @check

# Delete by key, error if not found
mutation MustDeleteMovie($id: UUID!) @transaction {
  movie_delete(id: $id) @check(expr: "this != null", message: "Movie not found, therefore nothing is deleted")
}

ใช้การผูก response เพื่อเชื่อมโยงการเปลี่ยนแปลงหลายขั้นตอน

แนวทางพื้นฐานในการสร้างระเบียนที่เกี่ยวข้อง เช่น Movie และ รายการ MovieMetadata ที่เชื่อมโยงกัน มีดังนี้

  1. เรียกการเปลี่ยนแปลง _insert สำหรับ Movie
  2. จัดเก็บคีย์ที่แสดงผลของภาพยนตร์ที่สร้างขึ้น
  3. จากนั้นเรียกการเปลี่ยนแปลง _insert ครั้งที่ 2 เพื่อสร้างระเบียน MovieMetadata

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

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

ใช้ response เพื่อตั้งค่าฟิลด์ด้วยค่าเซิร์ฟเวอร์

ในการเปลี่ยนแปลงรายการสิ่งที่ต้องทำต่อไปนี้

  • การผูก response แสดงถึงออบเจ็กต์การตอบกลับบางส่วนจนถึงตอนนี้ ซึ่งรวมถึงฟิลด์การเปลี่ยนแปลงระดับบนสุดทั้งหมดก่อนฟิลด์ปัจจุบัน
  • ระบบจะเข้าถึงผลลัพธ์ของการดำเนินการ todoList_insert เริ่มต้น ซึ่งแสดงผล id (คีย์) ในภายหลังใน response.todoList_insert.id เพื่อให้เรา แทรกรายการสิ่งที่ต้องทำใหม่ได้ทันที
mutation CreateTodoListWithFirstItem(
  $listName: String!,
  $itemContent: String!
) @transaction {
  # Sub-step 1:
  todoList_insert(data: {
    id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
    name: $listName,
  })
  # Sub-step 2:
  todo_insert(data: {
    listId_expr: "response.todoList_insert.id" # <-- Grab the newly generated ID from the partial response so far.
    content: $itemContent,
  })
}

ใช้ response เพื่อตรวจสอบฟิลด์โดยใช้ @check

response ยังใช้ได้ใน @check(expr: "...") ด้วย ดังนั้นคุณจึงใช้ สร้างตรรกะฝั่งเซิร์ฟเวอร์ที่ซับซ้อนยิ่งขึ้นได้ เมื่อรวมกับขั้นตอน query { … } ในการเปลี่ยนแปลง คุณจะทำสิ่งต่างๆ ได้มากขึ้นโดยไม่ต้องมีการเดินทางไปกลับระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์เพิ่มเติม

ในตัวอย่างต่อไปนี้ โปรดทราบว่า @check มีสิทธิ์เข้าถึง response.query อยู่แล้ว เนื่องจาก @check จะทำงานหลังขั้นตอนที่แนบอยู่เสมอ

mutation CreateTodoInNamedList(
  $listName: String!,
  $itemContent: String!
) @transaction {
  # Sub-step 1: Look up List.id by its name
  query
  @check(expr: "response.query.todoLists.size() > 0", message: "No such TodoList with the name!")
  @check(expr: "response.query.todoLists.size() < 2", message: "Ambiguous listName!") {
    todoLists(where: { name: $listName }) {
      id
    }
  }
  # Sub-step 2:
  todo_insert(data: {
    listId_expr: "response.todoLists[0].id" # <-- Now we have the parent list ID to insert to
    content: $itemContent,
  })
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับการผูก response ได้ใน เอกสารอ้างอิง CEL

ทำความเข้าใจการดำเนินการที่ถูกขัดจังหวะด้วย @transaction และ query @check

การเปลี่ยนแปลงหลายขั้นตอนอาจพบข้อผิดพลาดต่อไปนี้

  • การดำเนินการฐานข้อมูลอาจล้มเหลว
  • ตรรกะ `query @check` อาจยุติการดำเนินการ

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

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

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

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

คำสั่งสำหรับการเปลี่ยนแปลง SQL Connect

นอกเหนือจากคำสั่งที่คุณใช้ในการกำหนดประเภทและตารางแล้ว SQL Connect ยังมี @auth, @check, @redact และ @transaction เพื่อเพิ่มประสิทธิภาพการทำงานของการดำเนินการ

คำสั่ง นำไปใช้ได้กับ คำอธิบาย
@auth การค้นหาและการเปลี่ยนแปลง กำหนดนโยบายการให้สิทธิ์เข้าถึงสำหรับการค้นหาหรือการเปลี่ยนแปลง ดู คู่มือการให้สิทธิ์เข้าถึงและการรับรอง
@check ฟิลด์ query ในการดำเนินการหลายขั้นตอน ยืนยันว่าฟิลด์ที่ระบุมีอยู่ในผลการค้นหา ระบบจะใช้นิพจน์ Common Expression Language (CEL) เพื่อทดสอบค่าฟิลด์ ดู การดำเนินการหลายขั้นตอน
@redact การค้นหา ปกปิดส่วนหนึ่งของการตอบกลับจากไคลเอ็นต์ ดู การดำเนินการหลายขั้นตอน
@transaction การเปลี่ยนแปลง บังคับให้การเปลี่ยนแปลงทำงานในธุรกรรมฐานข้อมูลเสมอ ดู การดำเนินการหลายขั้นตอน

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

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