กำลังบันทึกข้อมูล

วิธีประหยัดอินเทอร์เน็ต

PUT เขียนหรือแทนที่ข้อมูลในเส้นทางที่กําหนด เช่น fireblog/users/user1/<data>
แผ่นแปะ อัปเดตคีย์บางรายการสำหรับเส้นทางที่กําหนดไว้โดยไม่ต้องแทนที่ข้อมูลทั้งหมด
POST เพิ่มลงในรายการข้อมูลในฐานข้อมูล Firebase ทุกครั้งที่เราส่งคําขอ POST ไคลเอ็นต์ Firebase จะสร้างคีย์ที่ไม่ซ้ำกัน เช่น fireblog/users/<unique-id>/<data>
ลบ นําข้อมูลจากข้อมูลอ้างอิงฐานข้อมูล Firebase ที่ระบุออก

การเขียนข้อมูลด้วย PUT

การดำเนินการเขียนพื้นฐานผ่าน REST API คือ PUT เราจะสร้างแอปพลิเคชันการเขียนบล็อกที่มีโพสต์และผู้ใช้เพื่อสาธิตการบันทึกข้อมูล ข้อมูลทั้งหมดสำหรับแอปพลิเคชันจะจัดเก็บไว้ในเส้นทาง "fireblog" ที่ URL ฐานข้อมูล Firebase "https://docs-examples.firebaseio.com/fireblog"

เริ่มต้นด้วยการบันทึกข้อมูลผู้ใช้บางส่วนลงในฐานข้อมูล Firebase เราจะจัดเก็บผู้ใช้แต่ละคนด้วยชื่อผู้ใช้ ที่ไม่ซ้ำกัน รวมทั้งจัดเก็บชื่อเต็มและวันเกิดของผู้ใช้ด้วย เนื่องจากผู้ใช้แต่ละรายจะมีชื่อผู้ใช้ที่ไม่ซ้ำกัน จึงควรใช้ PUT ที่นี่แทน POST เนื่องจากเรามีคีย์อยู่แล้วและไม่จำเป็นต้องสร้าง

เมื่อใช้ PUT เราจะเขียนสตริง ตัวเลข บูลีน อาร์เรย์ หรือออบเจ็กต์ JSON ใดก็ได้ลงในฐานข้อมูล Firebase ในกรณีนี้ เราจะส่งออบเจ็กต์ไปให้

curl -X PUT -d '{
  "alanisawesome": {
    "name": "Alan Turing",
    "birthday": "June 23, 1912"
  }
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'

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

curl -X PUT -d '"Alan Turing"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/name.json'
curl -X PUT -d '"June 23, 1912"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/birthday.json'

ตัวอย่าง 2 รายการข้างต้น การเขียนค่าพร้อมกันเป็นออบเจ็กต์และเขียนค่าดังกล่าวแยกต่างหากในตำแหน่งย่อย จะส่งผลให้ระบบบันทึกข้อมูลเดียวกันลงในฐานข้อมูล Firebase

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing"
    }
  }
}

คำขอที่สำเร็จจะแสดงด้วย200 OKรหัสสถานะ HTTP และการตอบกลับจะมีข้อมูลที่เราได้เขียนลงในฐานข้อมูล ตัวอย่างแรกจะทริกเกอร์เหตุการณ์เพียง 1 รายการในไคลเอ็นต์ที่ดูข้อมูลอยู่ ส่วนตัวอย่างที่ 2 จะทริกเกอร์ 2 รายการ โปรดทราบว่าหากมีข้อมูลอยู่ในเส้นทางของผู้ใช้อยู่แล้ว แนวทางแรกจะเขียนทับข้อมูลนั้น แต่วิธีที่ 2 จะแก้ไขเฉพาะค่าของโหนดย่อยแต่ละโหนดแยกกัน โดยไม่เปลี่ยนแปลงโหนดย่อยอื่นๆ PUT เทียบเท่ากับ set() ใน JavaScript SDK

การอัปเดตข้อมูลด้วย PATCH

เมื่อใช้คำขอ PATCH เราจะอัปเดตเด็กที่เฉพาะเจาะจงในสถานที่หนึ่งๆ ได้โดยไม่ต้องเขียนทับข้อมูลที่มีอยู่ เพิ่มชื่อเล่นของ Turing ลงในข้อมูลผู้ใช้ด้วยคำขอ PATCH ดังนี้

curl -X PATCH -d '{
  "nickname": "Alan The Machine"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

คำขอข้างต้นจะเขียน nickname ในออบเจ็กต์ alanisawesome ของเราโดยไม่ลบรายการย่อย name หรือ birthday โปรดทราบว่าหากเราออกคำขอ PUT ที่นี่แทน ระบบจะลบ name และ birthday ออกเนื่องจากไม่ได้รวมอยู่ในคำขอ ตอนนี้ข้อมูลในฐานข้อมูล Firebase มีลักษณะดังนี้

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    }
  }
}

คำขอที่สำเร็จจะระบุด้วยรหัสสถานะ HTTP 200 OK และการตอบกลับจะมีข้อมูลที่อัปเดตซึ่งเขียนไว้ในฐานข้อมูล

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

curl -X PATCH -d '{
  "alanisawesome/nickname": "Alan The Machine",
  "gracehopper/nickname": "Amazing Grace"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

หลังจากการอัปเดตนี้ ทั้ง Alan และ Grace ต่างก็เพิ่มชื่อเล่นแล้ว

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "date_of_birth": "December 9, 1906",
      "full_name": "Grace Hopper",
      "nickname": "Amazing Grace"
    }
  }
}

โปรดทราบว่าการพยายามอัปเดตออบเจ็กต์โดยการเขียนออบเจ็กต์ที่มีเส้นทางรวมอยู่ด้วยจะส่งผลให้เกิดลักษณะการทำงานที่แตกต่างออกไป มาดูกันว่าจะเกิดอะไรขึ้นหากเราพยายามอัปเดต Grace และ Alan ด้วยวิธีนี้

curl -X PATCH -d '{
  "alanisawesome": {"nickname": "Alan The Machine"},
  "gracehopper": {"nickname": "Amazing Grace"}
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

ซึ่งจะทําให้ลักษณะการทํางานแตกต่างออกไป กล่าวคือ การเขียนทับโหนด /fireblog/users ทั้งหมด

{
  "users": {
    "alanisawesome": {
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "nickname": "Amazing Grace"
    }
  }
}

การอัปเดตข้อมูลด้วยคําขอแบบมีเงื่อนไข

คุณสามารถใช้คำขอแบบมีเงื่อนไขซึ่งเทียบเท่ากับ REST เพื่ออัปเดตข้อมูลตามสถานะที่มีอยู่ได้ เช่น หากต้องการเพิ่มตัวนับการโหวตเห็นด้วย และต้องการให้จำนวนการโหวตเห็นด้วยหลายรายการพร้อมกันแสดงผลอย่างถูกต้อง ให้ใช้คําขอแบบมีเงื่อนไขเพื่อเขียนค่าใหม่ลงในตัวนับ แทนที่จะเขียน 2 ครั้งซึ่งจะเปลี่ยนตัวนับเป็นตัวเลขเดียวกัน คําขอเขียนรายการใดรายการหนึ่งจะดำเนินการไม่สําเร็จ จากนั้นคุณจะลองส่งคําขออีกครั้งโดยใช้ค่าใหม่ได้
  1. หากต้องการส่งคำขอแบบมีเงื่อนไขที่ตำแหน่งหนึ่งๆ ให้รับตัวระบุที่ไม่ซ้ำกันสำหรับข้อมูลปัจจุบันในตำแหน่งนั้นหรือ ETag หากข้อมูลเปลี่ยนแปลงที่ตำแหน่งดังกล่าว ETag จะเปลี่ยนไปด้วย คุณขอ ETag ได้ด้วยวิธีใดก็ได้ที่ไม่ใช่ PATCH ตัวอย่างต่อไปนี้ใช้คําขอ GET
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    การเรียก ETag ในส่วนหัวโดยเฉพาะจะแสดง ETag ของตำแหน่งที่ระบุในการตอบกลับ HTTP
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    10 // Current value of the data at the specified location
  2. ใส่ ETag ที่ส่งคืนมาในคำขอ PUT หรือ DELETE ครั้งถัดไปเพื่ออัปเดตข้อมูลที่ตรงกับค่า ETag นั้นโดยเฉพาะ จากตัวอย่าง หากต้องการอัปเดตตัวนับเป็น 11 หรือมากกว่าค่าที่ดึงข้อมูลครั้งแรก 10 หน่วย และทำให้คำขอไม่สำเร็จหากค่าไม่ตรงกันอีกต่อไป ให้ใช้โค้ดต่อไปนี้
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    หากค่าของข้อมูลที่ตำแหน่งที่ระบุยังคงเป็น 10 อยู่ ETag ในคำขอ PUT จะตรงกัน และคำขอจะสำเร็จโดยเขียน 11 ลงในฐานข้อมูล
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    Cache-Control: no-cache
    
    11 // New value of the data at the specified location, written by the conditional request
    หากตำแหน่งไม่ตรงกับ ETag อีกต่อไป ซึ่งอาจเกิดขึ้นหากผู้ใช้รายอื่นเขียนค่าใหม่ในฐานข้อมูล คำขอจะล้มเหลวโดยไม่ได้เขียนไปยังตำแหน่งดังกล่าว การตอบกลับที่แสดงผลจะมีค่าใหม่และ ETag
    HTTP/1.1 412 Precondition Failed
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    12 // New value of the data at the specified location
  3. ใช้ข้อมูลใหม่นี้หากตัดสินใจที่จะส่งคำขออีกครั้ง Realtime Database จะไม่ลองส่งคำขอแบบมีเงื่อนไขที่ไม่สำเร็จอีกครั้งโดยอัตโนมัติ อย่างไรก็ตาม คุณสามารถใช้ค่าใหม่และ ETag เพื่อสร้างคำขอแบบมีเงื่อนไขใหม่ที่มีข้อมูลที่แสดงผลจากการตอบกลับที่ไม่สำเร็จ

คำขอแบบมีเงื่อนไขตาม REST ใช้มาตรฐาน HTTPif-match อย่างไรก็ตาม ค่าเหล่านี้จะแตกต่างจากมาตรฐานดังนี้

  • คุณจะระบุค่า ETag ได้เพียงค่าเดียวสําหรับคําขอ if-match แต่ละรายการเท่านั้น
  • แม้ว่ามาตรฐานจะแนะนําให้แสดง ETag กับคําขอทั้งหมด แต่ Realtime Database จะแสดงเฉพาะ ETag กับคําขอที่มีส่วนหัว X-Firebase-ETag วิธีนี้ช่วยลดค่าใช้จ่ายในการเรียกเก็บเงินสำหรับคำขอมาตรฐาน

นอกจากนี้ คำขอแบบมีเงื่อนไขยังอาจช้ากว่าคำขอ REST ทั่วไปด้วย

การบันทึกรายการข้อมูล

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

curl -X POST -d '{
  "author": "alanisawesome",
  "title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'

ตอนนี้เส้นทาง posts มีข้อมูลต่อไปนี้

{
  "posts": {
    "-JSOpn9ZC54A4P4RoqVa": {
      "author": "alanisawesome",
      "title": "The Turing Machine"
    }
  }
}

โปรดทราบว่าระบบสร้างคีย์ -JSOpn9ZC54A4P4RoqVa ให้เราโดยอัตโนมัติเนื่องจากเราใช้คําขอ POST คำขอที่สำเร็จจะแสดงด้วยรหัสสถานะ HTTP 200 OK และการตอบกลับจะมีคีย์ของข้อมูลใหม่ที่เพิ่ม

{"name":"-JSOpn9ZC54A4P4RoqVa"}

การนำข้อมูลออก

หากต้องการนำข้อมูลจากฐานข้อมูลออก เราสามารถส่งคำขอ DELETE พร้อม URL ของเส้นทางที่ต้องการลบข้อมูล คำสั่งต่อไปนี้จะลบ Alan ออกจากเส้นทาง users

curl -X DELETE \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

คำขอ DELETE ที่สำเร็จจะแสดงด้วยรหัสสถานะ HTTP 200 OK พร้อมการตอบกลับที่มี JSON null

พารามิเตอร์ URI

REST API ยอมรับพารามิเตอร์ URI ต่อไปนี้เมื่อเขียนข้อมูลลงในฐานข้อมูล

การตรวจสอบสิทธิ์

พารามิเตอร์คำขอ auth ช่วยให้เข้าถึงข้อมูลที่ได้รับการปกป้องโดย Firebase Realtime Database Security Rules ได้ และรองรับคำขอทุกประเภท อาร์กิวเมนต์อาจเป็นข้อมูลลับของแอป Firebase หรือโทเค็นการตรวจสอบสิทธิ์ก็ได้ ซึ่งเราจะพูดถึงในส่วนการให้สิทธิ์ผู้ใช้ ในตัวอย่างต่อไปนี้ เราส่งคําขอ POST ที่มีพารามิเตอร์ auth โดยที่ CREDENTIAL คือคีย์ลับแอป Firebase หรือโทเค็นการตรวจสอบสิทธิ์

curl -X POST -d '{"Authenticated POST request"}' \
  'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

พิมพ์

พารามิเตอร์ print ช่วยให้เราระบุรูปแบบของคำตอบจากฐานข้อมูลได้ การเพิ่ม print=pretty ลงในคําขอจะแสดงผลข้อมูลในรูปแบบที่มนุษย์อ่านได้ คำขอ GET, PUT, POST, PATCH และ DELETE รองรับ print=pretty

หากต้องการซ่อนเอาต์พุตจากเซิร์ฟเวอร์เมื่อเขียนข้อมูล เราเพิ่ม print=silent ลงในคำขอได้ การตอบกลับที่ได้จะว่างเปล่าและระบุด้วยรหัสสถานะ HTTP 204 No Content หากคำขอสำเร็จ คำขอ GET, PUT, POST และ PATCH รองรับ print=silent

การเขียนค่าเซิร์ฟเวอร์

ค่าเซิร์ฟเวอร์สามารถเขียนไว้ในตำแหน่งโดยใช้ค่าตัวยึดตําแหน่ง ซึ่งเป็นออบเจ็กต์ที่มีคีย์ ".sv" รายการเดียว ค่าของคีย์นั้นคือประเภทของค่าเซิร์ฟเวอร์ที่เราต้องการตั้งค่า เช่น หากต้องการตั้งการประทับเวลาเมื่อสร้างผู้ใช้ เราอาจทําดังนี้

curl -X PUT -d '{".sv": "timestamp"}' \
  'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'

"timestamp" เป็นค่าเซิร์ฟเวอร์เพียงค่าเดียวที่รองรับ และเป็นเวลาที่นับจากยุค UNIX เป็นมิลลิวินาที

การปรับปรุงประสิทธิภาพการเขียน

หากเขียนข้อมูลจำนวนมากลงในฐานข้อมูล เราจะใช้พารามิเตอร์ print=silent เพื่อปรับปรุงประสิทธิภาพการเขียนและลดการใช้แบนด์วิดท์ได้ ในลักษณะการเขียนปกติ เซิร์ฟเวอร์จะตอบกลับด้วยข้อมูล JSON ที่เขียน เมื่อระบุ print=silent เซิร์ฟเวอร์จะปิดการเชื่อมต่อทันทีที่ได้รับข้อมูล ซึ่งจะช่วยลดการใช้แบนด์วิดท์

ในกรณีที่มีการส่งคำขอไปยังฐานข้อมูลหลายรายการ เราจะใช้การเชื่อมต่อ HTTPS ซ้ำได้โดยส่งคำขอ Keep-Alive ในส่วนหัว HTTP

เงื่อนไขข้อผิดพลาด

REST API จะแสดงรหัสข้อผิดพลาดในกรณีต่อไปนี้

รหัสสถานะ HTTP
400 คำขอไม่ถูกต้อง

เงื่อนไขข้อผิดพลาดอย่างใดอย่างหนึ่งต่อไปนี้

  • แยกวิเคราะห์ข้อมูล PUT หรือ POST ไม่ได้
  • ไม่มีข้อมูล PUT หรือ POST
  • คำขอพยายามPUTหรือPOSTข้อมูลที่มีขนาดใหญ่เกินไป
  • การเรียก REST API มีชื่อย่อยที่ไม่ถูกต้องเป็นส่วนหนึ่งของเส้นทาง
  • เส้นทางการเรียก REST API ยาวเกินไป
  • คำขอมีค่าเซิร์ฟเวอร์ที่ไม่รู้จัก
  • ไม่ได้กำหนดดัชนีสำหรับคำค้นหาใน Firebase Realtime Database Security Rules
  • คำขอไม่สนับสนุนพารามิเตอร์การค้นหาที่ระบุ
  • คําขอผสมพารามิเตอร์การค้นหาเข้ากับคําขอ GET แบบตื้น
401 ไม่ได้รับอนุญาต

เงื่อนไขข้อผิดพลาดอย่างใดอย่างหนึ่งต่อไปนี้

  • โทเค็นการตรวจสอบสิทธิ์หมดอายุแล้ว
  • โทเค็นการตรวจสอบสิทธิ์ที่ใช้ในคำขอไม่ถูกต้อง
  • ตรวจสอบสิทธิ์ด้วย Access_token ไม่สำเร็จ
  • คำขอดังกล่าวละเมิดFirebase Realtime Database Security Rulesของคุณ
404 ไม่พบ ไม่พบฐานข้อมูล Firebase ที่ระบุ
500 ข้อผิดพลาดภายในเซิร์ฟเวอร์ เซิร์ฟเวอร์แสดงข้อผิดพลาด โปรดดูรายละเอียดเพิ่มเติมในข้อความแสดงข้อผิดพลาด
503 ไม่พร้อมให้บริการ ฐานข้อมูลเรียลไทม์ของ Firebase ที่ระบุไม่พร้อมใช้งานชั่วคราว ซึ่งหมายความว่าไม่มีการพยายามส่งคำขอ

การรักษาความปลอดภัยของข้อมูล

Firebase มีภาษาด้านความปลอดภัยที่ช่วยให้เรากําหนดได้ว่าผู้ใช้รายใดมีสิทธิ์อ่านและเขียนโหนดข้อมูลต่างๆ อ่านข้อมูลเพิ่มเติมได้ใน Realtime Database Security Rules

เมื่อพูดถึงการบันทึกข้อมูลแล้ว เรามาเรียนรู้วิธีดึงข้อมูลจากฐานข้อมูล Firebase ผ่าน REST API กันต่อในส่วนถัดไป