ใช้การกลายพันธุ์ของ Data Connect

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

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

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

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

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

ลักษณะของการกลายพันธุ์ของ Data Connect

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

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

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

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

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

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

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

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

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

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

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

mutation CreateMovie($data: Movie_Data!) {
  movie_insert(data: $data) { key }
}

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

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

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

mutation UpdateMovie($myKey: Movie_Key!, $data: Movie_Data!) {
  movie_update(key: $myKey, data: $data) { key }
}

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

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

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

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

องค์ประกอบที่จำเป็นของการเปลี่ยนแปลง

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

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

หรือการอัปเดต/แทรก

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

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

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

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

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

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

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

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

นอกจากนี้ คุณยังใช้ประโยชน์จากข้อมูล เช่น รหัสผู้ใช้ ที่ส่งในออบเจ็กต์ Data 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สเกลาร์ในข้อมูลอ้างอิงสเกลาร์

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

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

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

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

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

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

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

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

  • การเชื่อมโยง CEL response ซึ่งจัดเก็บผลลัพธ์ที่สะสมของการกลายพันธุ์และการค้นหาทั้งหมดที่ดำเนินการในการดำเนินการที่ซับซ้อนแบบหลายขั้นตอน คุณสามารถ เข้าถึงการเชื่อมโยง 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 อาจไม่มีการดำเนินการใดๆ หากไม่มีระเบียนที่มีคีย์ที่ระบุ ในทำนองเดียวกัน การค้นหาอาจแสดงผลเป็นค่าว่างหรือรายการที่ว่างเปล่า โดยการเปลี่ยนแปลงเหล่านี้ จะไม่ถือเป็นข้อผิดพลาด จึงไม่ทำให้เกิดการย้อนกลับ

เพื่อป้องกันผลลัพธ์นี้ ให้ทดสอบว่าพบคีย์ได้หรือไม่โดยใช้คำสั่ง @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 mutation ที่ 2 เพื่อสร้างระเบียน MovieMetadata

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

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

ใช้ 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

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

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

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

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

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

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

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

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

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

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

คุณอาจสนใจ