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

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

ใส่ เขียนหรือแทนที่ข้อมูลไปยัง เส้นทางที่กำหนด เช่น 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'

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

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

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

หลังจากการอัปเดตนี้ ทั้งอลันและเกรซได้เพิ่มชื่อเล่น:

{
  "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 กับธุรกรรม เพื่ออัปเดตข้อมูลตามสถานะที่มีอยู่ ตัวอย่างเช่น หากคุณต้องการเพิ่มตัวนับ upvote และต้องการให้แน่ใจว่าจำนวนนั้นสะท้อนถึง upvotes พร้อมกันหลายรายการอย่างถูกต้อง ให้ใช้คำขอแบบมีเงื่อนไขเพื่อเขียนค่าใหม่ไปยังตัวนับ แทนที่จะเขียนสองครั้งที่เปลี่ยนตัวนับเป็นตัวเลขเดียวกัน คำขอเขียนรายการหนึ่งล้มเหลว จากนั้นคุณสามารถลองคำขออีกครั้งด้วยค่าใหม่
  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. ใช้ข้อมูลใหม่หากคุณตัดสินใจที่จะลองคำขออีกครั้ง ฐานข้อมูลเรียลไทม์ไม่ลองคำขอตามเงื่อนไขที่ล้มเหลวโดยอัตโนมัติ อย่างไรก็ตาม คุณสามารถใช้ค่าใหม่และ ETag เพื่อสร้างคำขอแบบมีเงื่อนไขใหม่พร้อมข้อมูลที่ส่งคืนโดยการตอบสนองที่ล้มเหลว

คำขอตามเงื่อนไขที่ใช้ REST ใช้มาตรฐาน HTTP if-match อย่างไรก็ตาม แตกต่างจากมาตรฐานด้วยวิธีต่อไปนี้:

  • คุณสามารถระบุค่า ETag ได้เพียงค่าเดียวสำหรับคำขอ if-match แต่ละรายการเท่านั้น ไม่สามารถป้อนหลายค่าได้
  • แม้ว่ามาตรฐานจะแนะนำให้ส่งคืน ETags พร้อมกับคำขอทั้งหมด แต่ Realtime Database จะส่งคืน ETags พร้อมกับคำขอที่มีส่วนหัว 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 และรองรับโดยคำขอทุกประเภท อาร์กิวเมนต์อาจเป็นได้ทั้งความลับของแอป 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 ในคำขอของเราจะส่งคืนข้อมูลในรูปแบบที่มนุษย์อ่านได้ print=pretty รองรับคำขอ GET , PUT , POST , PATCH และ DELETE

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

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

ค่าเซิร์ฟเวอร์สามารถเขียนที่ตำแหน่งโดยใช้ค่าตัวยึดซึ่งเป็นวัตถุที่มีคีย์ ".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
  • คำขอไม่สนับสนุนพารามิเตอร์การค้นหาที่ระบุไว้อย่างใดอย่างหนึ่ง
  • คำขอผสมพารามิเตอร์การค้นหากับคำขอ GET ที่ตื้น
401 ไม่ได้รับอนุญาต

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

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

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

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

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