รับการอ้างอิงฐานข้อมูล
หากต้องการอ่านหรือเขียนข้อมูลจากฐานข้อมูล คุณต้องมีอินสแตนซ์ของ DatabaseReference ดังนี้
DatabaseReference ref = FirebaseDatabase.instance.ref();
การอ่านและการเขียนรายการ
เพิ่มข้อมูลลงในรายการ
ใช้เมธอด push() เพื่อเพิ่มข้อมูลลงในรายการในแอปพลิเคชันแบบหลายผู้ใช้
เมธอด push() จะสร้างคีย์ที่ไม่ซ้ำกันทุกครั้งที่เพิ่มรายการย่อยใหม่ลงในการอ้างอิง Firebase ที่ระบุ การใช้คีย์ที่สร้างขึ้นโดยอัตโนมัติเหล่านี้สำหรับองค์ประกอบใหม่แต่ละรายการในรายการจะช่วยให้ไคลเอ็นต์หลายรายการเพิ่มรายการย่อยลงในตำแหน่งเดียวกันได้พร้อมกันโดยไม่มีข้อขัดแย้งในการเขียน คีย์ที่ไม่ซ้ำกันที่สร้างขึ้นโดย push() จะอิงตามการประทับเวลา ดังนั้นรายการในรายการจะเรียงตามลำดับเวลาโดยอัตโนมัติ
คุณสามารถใช้การอ้างอิงข้อมูลใหม่ที่เมธอด push() แสดงผลเพื่อรับค่าคีย์ที่สร้างขึ้นโดยอัตโนมัติของรายการย่อย หรือตั้งค่าข้อมูลสำหรับรายการย่อย พร็อพเพอร์ตี้ .key ของการอ้างอิง push() จะมีคีย์ที่สร้างขึ้นโดยอัตโนมัติ
คุณสามารถใช้คีย์ที่สร้างขึ้นโดยอัตโนมัติเหล่านี้เพื่อลดความซับซ้อนในการทำให้โครงสร้างข้อมูลแบนราบ ดูข้อมูลเพิ่มเติมได้ที่ตัวอย่างการกระจายข้อมูล
ตัวอย่างเช่น คุณสามารถใช้ push() เพื่อเพิ่มโพสต์ใหม่ลงในรายการโพสต์ในแอปพลิเคชันโซเชียลได้ ดังนี้
DatabaseReference postListRef = FirebaseDatabase.instance.ref("posts");
DatabaseReference newPostRef = postListRef.push();
newPostRef.set({
// ...
});
รอรับเหตุการณ์ย่อย
ระบบจะทริกเกอร์เหตุการณ์ย่อยเพื่อตอบสนองต่อการดำเนินการที่เฉพาะเจาะจงซึ่งเกิดขึ้นกับรายการย่อยของโหนดจากการดำเนินการ เช่น การเพิ่มรายการย่อยใหม่ผ่านเมธอด push() หรือการอัปเดตรายการย่อยผ่านเมธอด update()
| เหตุการณ์ | การใช้งานทั่วไป |
|---|---|
onChildAdded |
ดึงข้อมูลรายการหรือรอรับการเพิ่มลงในรายการ ระบบจะทริกเกอร์เหตุการณ์นี้ 1 ครั้งสำหรับรายการย่อยที่มีอยู่แต่ละรายการ จากนั้นจะทริกเกอร์อีกครั้ง ทุกครั้งที่เพิ่มรายการย่อยใหม่ลงในเส้นทางที่ระบุ ระบบจะส่งสแนปช็อตที่มีข้อมูลของรายการย่อยใหม่ไปยัง Listener |
onChildChanged |
รอรับการเปลี่ยนแปลงรายการในรายการ ระบบจะทริกเกอร์เหตุการณ์นี้ทุกครั้งที่มีการแก้ไขโหนดรายการย่อย ซึ่งรวมถึง การแก้ไขรายการที่สืบทอดมาจากโหนดรายการย่อย สแนปช็อตที่ส่ง ไปยัง Listener เหตุการณ์จะมีข้อมูลที่อัปเดตของรายการย่อย |
onChildRemoved |
รอรับการนำรายการออกจากรายการ ระบบจะทริกเกอร์เหตุการณ์นี้เมื่อ มีการนำรายการย่อยออก สแนปช็อตที่ส่งไปยังบล็อก Callback จะมีข้อมูลของรายการย่อยที่นำออก |
onChildMoved |
รอรับการเปลี่ยนแปลงลำดับรายการในรายการที่เรียงลำดับแล้ว เหตุการณ์ onChildMoved จะเกิดขึ้นหลังเหตุการณ์ onChildChanged เสมอ ซึ่งทำให้ลำดับของรายการ เปลี่ยนแปลง (โดยอิงตามเมธอดการเรียงลำดับปัจจุบัน) |
เหตุการณ์เหล่านี้ร่วมกันจะมีประโยชน์สำหรับการรอรับการเปลี่ยนแปลงโหนดที่เฉพาะเจาะจงในฐานข้อมูล ตัวอย่างเช่น แอปบล็อกโซเชียลอาจใช้เมธอดเหล่านี้ร่วมกันเพื่อตรวจสอบกิจกรรมในความคิดเห็นของโพสต์ ดังที่แสดงด้านล่าง
final commentsRef = FirebaseDatabase.instance.ref("post-comments/$postId");
commentsRef.onChildAdded.listen((event) {
// A new comment has been added, so add it to the displayed list.
});
commentsRef.onChildChanged.listen((event) {
// A comment has changed; use the key to determine if we are displaying this
// comment and if so displayed the changed comment.
});
commentsRef.onChildRemoved.listen((event) {
// A comment has been removed; use the key to determine if we are displaying
// this comment and if so remove it.
});
รอรับเหตุการณ์ค่า
แม้ว่าการรอรับเหตุการณ์ย่อยจะเป็นวิธีที่แนะนำในการอ่านรายการข้อมูล แต่ก็มีบางสถานการณ์ที่การรอรับเหตุการณ์ค่าในการอ้างอิงรายการจะมีประโยชน์
การแนบ Listener value กับรายการข้อมูลจะแสดงผลรายการข้อมูลทั้งหมดเป็นสแนปช็อตเดียว ซึ่งคุณสามารถวนซ้ำเพื่อเข้าถึงรายการย่อยแต่ละรายการได้
แม้ว่าจะมีผลการค้นหาที่ตรงกับคำค้นหาเพียงรายการเดียว แต่สแนปช็อตก็ยังคงเป็นรายการ ซึ่งมีเพียงรายการเดียว หากต้องการเข้าถึงรายการ คุณต้องวนซ้ำผลลัพธ์ ดังนี้
myTopPostsQuery.onValue.listen((event) {
for (final child in event.snapshot.children) {
// Handle the post.
}
}, onError: (error) {
// Error.
});
รูปแบบนี้จะมีประโยชน์เมื่อคุณต้องการดึงข้อมูลรายการย่อยทั้งหมดของรายการในการดำเนินการเดียว แทนที่จะรอรับเหตุการณ์การเพิ่มรายการย่อย
การจัดเรียงและการกรองข้อมูล
คุณสามารถใช้คลาส Query เพื่อดึงข้อมูลที่จัดเรียงตามคีย์ ตามค่า หรือตามค่าของรายการย่อย นอกจากนี้ คุณยังกรองผลลัพธ์ที่จัดเรียงแล้วให้แสดงผลลัพธ์ตามจำนวนที่เฉพาะเจาะจง หรือตามช่วงคีย์หรือค่าที่ต้องการได้ด้วย
จัดเรียงข้อมูล
หากต้องการดึงข้อมูลที่จัดเรียงแล้ว ให้เริ่มต้นด้วยการระบุเมธอดการเรียงลำดับรายการใดรายการหนึ่งเพื่อกำหนดวิธีจัดเรียงผลลัพธ์
| เมธอด | การใช้งาน |
|---|---|
orderByChild() |
จัดเรียงผลลัพธ์ตามค่าของคีย์รายการย่อยที่ระบุหรือเส้นทางรายการย่อยที่ซ้อนกัน |
orderByKey() |
จัดเรียงผลลัพธ์ตามคีย์รายการย่อย |
orderByValue() |
จัดเรียงผลลัพธ์ตามค่ารายการย่อย |
คุณใช้เมธอดการเรียงลำดับรายการได้เพียงรายการเดียว ในแต่ละครั้ง การเรียกเมธอดการเรียงลำดับรายการหลายครั้งในการค้นหาเดียวกันจะทำให้เกิดข้อผิดพลาด
ตัวอย่างต่อไปนี้แสดงวิธีดึงข้อมูลรายการโพสต์ยอดนิยมของผู้ใช้ที่จัดเรียงตามจำนวนดาว
final myUserId = FirebaseAuth.instance.currentUser?.uid;
final topUserPostsRef = FirebaseDatabase.instance
.ref("user-posts/$myUserId")
.orderByChild("starCount");
ตัวอย่างนี้กำหนดการค้นหาที่เมื่อรวมกับ Listener รายการย่อย แล้ว จะซิงค์ไคลเอ็นต์กับโพสต์ของผู้ใช้จากเส้นทางในฐานข้อมูล โดยอิงตามรหัสผู้ใช้ และจัดเรียงตามจำนวนดาวที่แต่ละโพสต์ได้รับ เทคนิคการใช้รหัสเป็นคีย์ดัชนีนี้เรียกว่าการกระจายข้อมูล คุณสามารถอ่าน ข้อมูลเพิ่มเติมเกี่ยวกับเทคนิคนี้ได้ใน หัวข้อการจัดโครงสร้างฐานข้อมูล
การเรียกเมธอด orderByChild() จะระบุคีย์รายการย่อยที่จะใช้จัดเรียงผลลัพธ์ ในกรณีนี้ ระบบจะจัดเรียงโพสต์ตามค่าของรายการย่อย
ที่เกี่ยวข้อง "starCount" นอกจากนี้ คุณยังจัดเรียงการค้นหาตามรายการย่อยที่ซ้อนกันได้ด้วย ในกรณีที่คุณมีข้อมูลลักษณะดังนี้
"posts": {
"ts-functions": {
"metrics": {
"views" : 1200000,
"likes" : 251000,
"shares": 1200,
},
"title" : "Why you should use TypeScript for writing Cloud Functions",
"author": "Doug",
},
"android-arch-3": {
"metrics": {
"views" : 900000,
"likes" : 117000,
"shares": 144,
},
"title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
"author": "Doug",
}
},
ในกรณีนี้ เราสามารถจัดเรียงองค์ประกอบรายการตามค่าที่ซ้อนอยู่ใต้คีย์ metrics ได้โดยการระบุเส้นทางสัมพัทธ์ไปยังรายการย่อยที่ซ้อนกันในการเรียก orderByChild()
final mostViewedPosts =
FirebaseDatabase.instance.ref('posts').orderByChild('metrics/views');
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีจัดเรียงข้อมูลประเภทอื่นๆ ได้ที่ หัวข้อ วิธีจัดเรียงข้อมูลการค้นหา
การกรองข้อมูล
หากต้องการกรองข้อมูล คุณสามารถรวมเมธอดการจำกัดหรือเมธอดช่วงใดก็ได้กับเมธอดการเรียงลำดับรายการเมื่อสร้างการค้นหา
| เมธอด | การใช้งาน |
|---|---|
limitToFirst() |
กำหนดจำนวนสูงสุดของรายการที่จะแสดงผลจากจุดเริ่มต้นของ รายการผลลัพธ์ที่จัดเรียงแล้ว |
limitToLast() |
กำหนดจำนวนสูงสุดของรายการที่จะแสดงผลจากจุดสิ้นสุดของรายการผลลัพธ์ที่จัดเรียงแล้ว |
startAt() |
แสดงรายการที่มากกว่าหรือเท่ากับคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับเมธอดการเรียงลำดับรายการที่เลือก |
startAfter() |
แสดงรายการที่มากกว่าคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับเมธอดการเรียงลำดับรายการที่เลือก |
endAt() |
แสดงรายการที่น้อยกว่าหรือเท่ากับคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับเมธอดการเรียงลำดับรายการที่เลือก |
endBefore() |
แสดงรายการที่น้อยกว่าคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับเมธอดการเรียงลำดับรายการที่เลือก |
equalTo() |
แสดงรายการที่เท่ากับคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับ เมธอดการเรียงลำดับรายการที่เลือก |
คุณสามารถรวมฟังก์ชันการจำกัดหรือฟังก์ชันช่วงหลายรายการได้ ซึ่งแตกต่างจากเมธอดการเรียงลำดับรายการ
ตัวอย่างเช่น คุณสามารถรวมเมธอด startAt() และ endAt() เพื่อจำกัดผลลัพธ์ให้แสดงเฉพาะค่าในช่วงที่ระบุ
จำกัดจำนวนผลลัพธ์
คุณสามารถใช้เมธอด limitToFirst() และ limitToLast() เพื่อกำหนดจำนวนสูงสุดของรายการย่อยที่จะซิงค์สำหรับเหตุการณ์ที่กำหนด ตัวอย่างเช่น หากคุณใช้ limitToFirst() เพื่อกำหนดขีดจำกัดไว้ที่ 100 คุณจะได้รับเหตุการณ์ onChildAdded ไม่เกิน 100 รายการในตอนแรก หากคุณเก็บรายการไว้ในฐานข้อมูล Firebase น้อยกว่า 100 รายการ ระบบจะทริกเกอร์เหตุการณ์ onChildAdded สำหรับแต่ละรายการ
เมื่อรายการมีการเปลี่ยนแปลง คุณจะได้รับเหตุการณ์ onChildAdded สำหรับรายการที่เข้าสู่การค้นหา และเหตุการณ์ onChildRemoved สำหรับรายการที่ออกจากผลการค้นหา เพื่อให้จำนวนรวมยังคงอยู่ที่ 100 รายการ
ตัวอย่างต่อไปนี้แสดงวิธีที่แอปบล็อกตัวอย่างกำหนดการค้นหาเพื่อดึงข้อมูลรายการโพสต์ล่าสุด 100 รายการจากผู้ใช้ทั้งหมด
final recentPostsRef = FirebaseDatabase.instance.ref('posts').limitToLast(100);
ตัวอย่างนี้กำหนดการค้นหาเท่านั้น หากต้องการซิงค์ข้อมูลจริง คุณต้องแนบ Listener
กรองตามคีย์หรือค่า
คุณสามารถใช้ startAt(), startAfter(),endAt(), endBefore() และ equalTo() เพื่อเลือกจุดเริ่มต้น จุดสิ้นสุด และจุดเทียบเท่าที่กำหนดเองสำหรับการค้นหา ซึ่งอาจมีประโยชน์สำหรับการแบ่งหน้าข้อมูลหรือการค้นหารายการที่มีรายการย่อยที่มีค่าที่เฉพาะเจาะจง
วิธีจัดเรียงข้อมูลการค้นหา
ส่วนนี้จะอธิบายวิธีจัดเรียงข้อมูลตามเมธอดการเรียงลำดับรายการแต่ละรายการในคลาส Query
orderByChild
เมื่อใช้ orderByChild() ระบบจะจัดเรียงข้อมูลที่มีคีย์รายการย่อยที่ระบุไว้ดังนี้
- รายการย่อยที่มีค่า
nullสำหรับคีย์รายการย่อยที่ระบุจะแสดง ก่อน - รายการย่อยที่มีค่า
falseสำหรับคีย์รายการย่อยที่ระบุ จะแสดงถัดไป หากรายการย่อยหลายรายการมีค่าfalseระบบจะจัดเรียงรายการเหล่านั้นตามลำดับพจนานุกรมตามคีย์ - รายการย่อยที่มีค่า
trueสำหรับคีย์รายการย่อยที่ระบุ จะแสดงถัดไป หากรายการย่อยหลายรายการมีค่าtrueระบบจะจัดเรียงรายการเหล่านั้นตามลำดับพจนานุกรมตามคีย์ - รายการย่อยที่มีค่าเป็นตัวเลขจะแสดงถัดไป โดยจัดเรียงจากน้อยไปมาก หากรายการย่อยหลายรายการมีค่าตัวเลขเดียวกันสำหรับโหนดรายการย่อยที่ระบุ ระบบจะจัดเรียงรายการเหล่านั้นตามคีย์
- สตริงจะแสดงหลังตัวเลขและจัดเรียงตามลำดับพจนานุกรมจากน้อยไปมาก หากรายการย่อยหลายรายการมีค่าเดียวกันสำหรับโหนดรายการย่อยที่ระบุ ระบบจะจัดเรียงรายการเหล่านั้นตามลำดับพจนานุกรมตามคีย์
- ออบเจ็กต์จะแสดงเป็นรายการสุดท้ายและจัดเรียงตามลำดับพจนานุกรมตามคีย์จากน้อยไปมาก
orderByKey
เมื่อใช้ orderByKey() เพื่อจัดเรียงข้อมูล ระบบจะแสดงผลข้อมูลตามลำดับจากน้อยไปมากตามคีย์
- รายการย่อยที่มีคีย์ที่แยกวิเคราะห์เป็นจำนวนเต็ม 32 บิตได้จะแสดงก่อน โดยจัดเรียงจากน้อยไปมาก
- รายการย่อยที่มีค่าสตริงเป็นคีย์จะแสดงถัดไป โดยจัดเรียงตามลำดับพจนานุกรมจากน้อยไปมาก
orderByValue
เมื่อใช้ orderByValue() ระบบจะจัดเรียงรายการย่อยตามค่า เกณฑ์การจัดเรียงจะเหมือนกับใน orderByChild() ยกเว้นว่าจะใช้ค่าของโหนดแทนค่าของคีย์รายการย่อยที่ระบุ
ยกเลิกการแนบ Listener
ระบบจะนำ Callback ออกโดยการเรียกเมธอด off() ในการอ้างอิงฐานข้อมูล Firebase
คุณสามารถนำ Listener รายการเดียวออกได้โดยส่ง Listener เป็นพารามิเตอร์ไปยัง off()
การเรียก off() ในตำแหน่งที่ไม่มีอาร์กิวเมนต์จะนำ Listener ทั้งหมดในตำแหน่งนั้นออก
การเรียก off() ใน Listener หลักจะไม่นำ Listener ที่ลงทะเบียนไว้ในโหนดรายการย่อยออกโดยอัตโนมัติ คุณต้องเรียก off() ใน Listener รายการย่อยด้วยเพื่อนำ Callback ออก