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

วิธีบันทึกข้อมูล

PUT เขียนหรือแทนที่ข้อมูลตามเส้นทางที่กำหนด เช่น fireblog/users/user1/<data>
แผ่นแปะ อัปเดตคีย์บางรายการสำหรับเส้นทางที่กำหนดโดยไม่ต้องแทนที่ข้อมูลทั้งหมด
โพสต์ เพิ่มลงในรายการข้อมูลในฐานข้อมูล 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"
    }
  }
}

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

การอัปเดตข้อมูลด้วยแพตช์

การใช้คำขอ 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 หรือ 1 ที่ใหญ่กว่าค่าแรกที่ดึงมาซึ่งก็คือ 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 จะใช้มาตรฐาน HTTP if-match อย่างไรก็ตาม ค่าเหล่านี้จะแตกต่างจากมาตรฐานดังนี้

  • คุณระบุค่า ETag ได้เพียง 1 ค่าต่อคำขอ 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 ของเส้นทางที่เราต้องการลบข้อมูล ข้อมูลต่อไปนี้จะลบอลันออกจากเส้นทาง 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 และรองรับคำขอทุกประเภท อาร์กิวเมนต์อาจเป็นข้อมูลลับของแอป 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 Epoch ในหน่วยมิลลิวินาที

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

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

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

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

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

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

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

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

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

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

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

Firebase มีภาษาเพื่อความปลอดภัยที่ช่วยให้เรากำหนดได้ว่าผู้ใช้คนใดมีสิทธิ์เข้าถึงโหนดข้อมูลแบบอ่านและเขียนได้ อ่านข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อนี้ได้ในกฎความปลอดภัยของฐานข้อมูลแบบเรียลไทม์

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