การเรียกข้อมูลด้วยฐานข้อมูลเรียลไทม์ของ Firebase สำหรับ C++

เอกสารนี้ครอบคลุมข้อมูลพื้นฐานของการดึงข้อมูล รวมถึงวิธีเรียงลำดับและกรองข้อมูลใน Firebase

ก่อนเริ่มต้น

ตรวจสอบว่าคุณได้ตั้งค่าแอปแล้วและเข้าถึงฐานข้อมูลได้ตามที่อธิบายไว้ในคู่มือGet Started

กำลังดึงข้อมูล

ข้อมูล Firebase ได้รับโดยการเรียกแบบครั้งเดียวไปยัง GetValue() หรือแนบ ValueListener ในข้อมูลอ้างอิง FirebaseDatabase ระบบจะเรียกใช้ Listener ค่า 1 ครั้งสำหรับสถานะเริ่มต้นของข้อมูล และเรียกอีกครั้งทุกครั้งที่ข้อมูลเปลี่ยนแปลง

รับ DatabaseReference

ในการเขียนข้อมูลไปยังฐานข้อมูล คุณต้องมีอินสแตนซ์ของ DatabaseReference:

    // Get the root reference location of the database.
    firebase::database::DatabaseReference dbref = database->GetReference();

อ่านข้อมูลครั้งเดียว

คุณใช้เมธอด GetValue() เพื่ออ่านสแนปชอตแบบคงที่ของเนื้อหาในเส้นทางที่ระบุได้ 1 ครั้ง ผลลัพธ์ของงานจะมีสแนปชอตที่มีข้อมูลทั้งหมดที่ตำแหน่งนั้น รวมถึงข้อมูลย่อย หากไม่มีข้อมูล สแนปชอตที่แสดงผลคือ null

  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("Leaders").GetValue();

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

  // In the game loop that polls for the result...

  if (result.status() != firebase::kFutureStatusPending) {
    if (result.status() != firebase::kFutureStatusComplete) {
      LogMessage("ERROR: GetValue() returned an invalid result.");
      // Handle the error...
    } else if (result.error() != firebase::database::kErrorNone) {
      LogMessage("ERROR: GetValue() returned error %d: %s", result.error(),
                 result.error_message());
      // Handle the error...
    } else {
      firebase::database::DataSnapshot snapshot = result.result();
      // Do something with the snapshot...
    }
  }

ซึ่งจะแสดงการตรวจสอบข้อผิดพลาดพื้นฐาน โปรดดูข้อมูลอ้างอิง firebase::Future เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบข้อผิดพลาดและวิธีพิจารณาว่าผลลัพธ์พร้อมเมื่อใด

ฟังเหตุการณ์

คุณเพิ่ม Listener เพื่อติดตามการเปลี่ยนแปลงของข้อมูลได้โดยทำดังนี้

คลาสฐาน ValueListener

การโทรกลับ การใช้งานทั่วไป
OnValueChanged อ่านและรับฟังการเปลี่ยนแปลงเนื้อหาทั้งหมดของเส้นทาง

คลาสฐาน OnChildListener

OnChildAdded ดึงข้อมูลรายการต่างๆ หรือฟังการเพิ่มในรายการ แนะนำให้ใช้กับ OnChildChanged และ OnChildRemoved เพื่อตรวจสอบการเปลี่ยนแปลงในรายการ
OnChildChanged ฟังการเปลี่ยนแปลงของรายการ ใช้ร่วมกับ OnChildAdded และ OnChildRemoved เพื่อตรวจสอบการเปลี่ยนแปลงของรายการ
OnChildRemoved คอยฟังรายการที่ถูกนำออก ใช้ร่วมกับ OnChildAdded และ OnChildChanged เพื่อตรวจสอบการเปลี่ยนแปลงของรายการ
OnChildMoved คอยฟังการเปลี่ยนแปลงลำดับของรายการในรายการที่เรียงลำดับ การติดต่อกลับของ OnChildMoved จะตามการเรียกกลับ OnChildChanged เสมอเนื่องจากลำดับของรายการมีการเปลี่ยนแปลง (อิงตามวิธีการสั่งซื้อปัจจุบัน)

คลาส ValueListener

คุณใช้ Callback OnValueChanged เพื่อสมัครใช้บริการการเปลี่ยนแปลงเนื้อหาในเส้นทางที่ระบุได้ Callback นี้จะถูกเรียกใช้ 1 ครั้งเมื่อมีการแนบ Listener และอีกครั้งทุกครั้งที่ข้อมูลรวมถึงเด็กด้วย มีการเปลี่ยนแปลง ระบบจะติดต่อกลับผ่านสแนปชอตที่มีข้อมูลในตำแหน่งดังกล่าว รวมถึงข้อมูลย่อย หากไม่มีข้อมูล สแนปชอตที่แสดงผลคือ null

ตัวอย่างต่อไปนี้สาธิตว่าเกมดึงข้อมูลคะแนนของลีดเดอร์บอร์ดจากฐานข้อมูล

  class LeadersValueListener : public firebase::database::ValueListener {
   public:
    void OnValueChanged(
        const firebase::database::DataSnapshot& snapshot) override {
      // Do something with the data in snapshot...
    }
    void OnCancelled(const firebase::database::Error& error_code,
                     const char* error_message) override {
      LogMessage("ERROR: LeadersValueListener canceled: %d: %s", error_code,
                 error_message);
    }
  };

  // Elsewhere in the code...

  LeadersValueListener* listener = new LeadersValueListener();
  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("Leaders").AddValueListener(listener);

ผลลัพธ์ Future&ltDataSnapshot&gt มีข้อมูลในตำแหน่งที่ระบุไว้ในฐานข้อมูล ณ เวลาที่เกิดเหตุการณ์ การเรียกใช้ value() ในสแนปชอต จะแสดงผล Variant ที่แสดงถึงข้อมูล

ในตัวอย่างนี้ ระบบจะลบล้างเมธอด OnCancelled ด้วยเพื่อดูว่าการอ่านถูกยกเลิกหรือไม่ เช่น การอ่านอาจถูกยกเลิกหากไคลเอ็นต์ไม่มีสิทธิ์อ่านจากตำแหน่งฐานข้อมูล Firebase database::Error จะระบุสาเหตุของความล้มเหลว

คลาส ChildListener

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

  class SessionCommentsChildListener : public firebase::database::ChildListener {
   public:
    void OnChildAdded(const firebase::database::DataSnapshot& snapshot,
                      const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnChildChanged(const firebase::database::DataSnapshot& snapshot,
                        const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnChildRemoved(
        const firebase::database::DataSnapshot& snapshot) override {
      // Do something with the data in snapshot ...
    }
    void OnChildMoved(const firebase::database::DataSnapshot& snapshot,
                      const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnCancelled(const firebase::database::Error& error_code,
                     const char* error_message) override {
      LogMessage("ERROR: SessionCommentsChildListener canceled: %d: %s",
                 error_code, error_message);
    }
  };

  // elsewhere ....

  SessionCommentsChildListener* listener = new SessionCommentsChildListener();
  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("GameSessionComments").AddChildListener(listener);

โดยปกติ Callback OnChildAdded จะใช้เพื่อดึงรายการต่างๆ ในฐานข้อมูล Firebase ระบบจะเรียกการเรียกกลับ OnChildAdded 1 ครั้งสำหรับผู้เผยแพร่โฆษณาย่อยที่มีอยู่แต่ละรายการ และเรียกอีกครั้งทุกครั้งที่มีการเพิ่มรายการย่อยใหม่ลงในเส้นทางที่ระบุ ระบบจะส่งผ่านสแนปชอตที่มีข้อมูลของ Listener ใหม่

ระบบจะเรียกการเรียกกลับ OnChildChanged ทุกครั้งที่มีการแก้ไขโหนดย่อย ซึ่งรวมถึงการแก้ไขรายการสืบทอดของโหนดย่อย โดยปกติแล้วจะใช้ร่วมกับการเรียก OnChildAdded และ OnChildRemoved เพื่อตอบสนองต่อการเปลี่ยนแปลงรายการต่างๆ สแนปชอตที่ส่งไปยังผู้ฟังจะมีข้อมูลที่อัปเดตสำหรับผู้เผยแพร่โฆษณาย่อย

ระบบจะเรียกใช้ Callback OnChildRemoved เมื่อมีการนำบุตรหลานโดยตรงออก โดยปกติแล้วจะใช้ร่วมกับ Callback OnChildAdded และ OnChildChanged สแนปชอตที่ส่งไปยัง Callback ประกอบด้วย ข้อมูลสำหรับบัญชีย่อยที่นำออกไปแล้ว

ระบบจะเรียกใช้ Callback OnChildMoved เมื่อมีการเรียกใช้ OnChildChanged จากการอัปเดตที่ทำให้เกิดการจัดเรียงรายการย่อยใหม่ โดยจะใช้กับข้อมูลที่เรียงลำดับด้วย OrderByChild หรือ OrderByValue

การจัดเรียงและกรองข้อมูล

คุณสามารถใช้คลาส Query ของ Realtime Database เพื่อเรียกข้อมูลที่จัดเรียงตามคีย์ ค่า หรือค่าของบุตรหลานได้ นอกจากนี้ คุณยังกรองผลการค้นหาที่จัดเรียงแล้วตามจำนวนผลลัพธ์ที่เจาะจง หรือช่วงของคีย์หรือค่าได้ด้วย

จัดเรียงข้อมูล

หากต้องการเรียกดูข้อมูลที่จัดเรียงแล้ว ให้เริ่มด้วยการระบุวิธีการเรียงลำดับตามวิธีใดวิธีหนึ่งเพื่อกำหนดลำดับของผลลัพธ์ ดังนี้

วิธีการ การใช้งาน
OrderByChild() เรียงลำดับผลลัพธ์ตามค่าของคีย์ย่อยที่ระบุ
OrderByKey() เรียงลำดับผลการค้นหาตามคีย์ย่อย
OrderByValue() เรียงลำดับผลลัพธ์ตามค่าย่อย

คุณใช้วิธีสั่งซื้อได้ครั้งละ 1 วิธีเท่านั้น การเรียกใช้เมธอดตามลำดับ หลายครั้งในข้อความค้นหาเดียวกันทำให้เกิดข้อผิดพลาด

ตัวอย่างต่อไปนี้แสดงวิธีสมัครรับข้อมูลลีดเดอร์บอร์ดคะแนนซึ่งจัดเรียงตามคะแนน

  firebase::database::Query query =
    dbRef.GetReference("Leaders").OrderByChild("score");

  // To get the resulting DataSnapshot either use query.GetValue() and poll the
  // future, or use query.AddValueListener() and register to handle the
  // OnValueChanged callback.

ซึ่งจะกำหนด firebase::Query ที่เมื่อใช้ร่วมกับ ValueListener จะซิงค์ไคลเอ็นต์กับลีดเดอร์บอร์ดในฐานข้อมูล โดยเรียงลำดับตามคะแนนของแต่ละรายการ อ่านเพิ่มเติมเกี่ยวกับการจัดโครงสร้างข้อมูลอย่างมีประสิทธิภาพได้ในจัดโครงสร้างฐานข้อมูล

การเรียกเมธอด OrderByChild() จะระบุคีย์ย่อยเพื่อเรียงลำดับผลลัพธ์ ในกรณีนี้ ผลลัพธ์จะจัดเรียงตามค่าของค่า "score" ในองค์ประกอบย่อยแต่ละรายการ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเรียงลำดับข้อมูลประเภทอื่นๆ ได้จากวิธีเรียงลำดับข้อมูลคำค้นหา

การกรองข้อมูล

ในการกรองข้อมูล คุณสามารถรวมวิธีการจำกัดหรือช่วงใดๆ กับเมธอดตามลำดับเมื่อสร้างคำค้นหา

วิธีการ การใช้งาน
LimitToFirst() กำหนดจำนวนรายการสูงสุดที่จะแสดงผลจากจุดเริ่มต้นของรายการผลลัพธ์ที่มีการเรียงลำดับ
LimitToLast() กำหนดจำนวนรายการสูงสุดที่จะแสดงผลจากส่วนท้ายรายการผลลัพธ์ที่เรียงลำดับ
StartAt() ส่งคืนสินค้าที่มากกว่าหรือเท่ากับคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับวิธีการเรียงลำดับที่เลือกไว้
EndAt() ส่งคืนสินค้าที่น้อยกว่าหรือเท่ากับคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับวิธีการเรียงลำดับที่เลือกไว้
EqualTo() ส่งคืนสินค้าที่มีขนาดเท่ากับคีย์หรือค่าที่ระบุ ทั้งนี้ขึ้นอยู่กับวิธีการเรียงลำดับตามที่เลือก

คุณสามารถรวมฟังก์ชันขีดจำกัดหรือช่วงได้หลายรายการ ซึ่งต่างจากเมธอดการเรียงลำดับ เช่น คุณรวมเมธอด StartAt() และ EndAt() เพื่อจำกัดผลลัพธ์ให้อยู่ในช่วงของค่าที่ระบุได้

แม้ว่าข้อความค้นหาจะมีข้อความที่ตรงกันเพียงรายการเดียว แต่สแนปชอตก็ยังคงเป็นลิสต์รายการ ซึ่งมีเพียงรายการเดียวเท่านั้น

จำกัดจำนวนผลการค้นหา

คุณใช้เมธอด LimitToFirst() และ LimitToLast() เพื่อกำหนดจำนวนสูงสุดย่อยที่จะซิงค์สำหรับ Callback ที่กำหนดได้ เช่น หากใช้ LimitToFirst() เพื่อกำหนดขีดจำกัด 100 รายการ ในตอนแรกคุณจะได้รับ Callback ของ OnChildAdded ไม่เกิน 100 รายการเท่านั้น หากคุณมีรายการที่จัดเก็บไว้ในฐานข้อมูล Firebase น้อยกว่า 100 รายการ การเรียกกลับ OnChildAdded จะเริ่มทำงานสำหรับแต่ละรายการ

เมื่อรายการเปลี่ยนแปลง คุณจะได้รับ Callback OnChildAdded รายการสําหรับรายการที่ป้อนคําค้นหาและ OnChildRemoved Callback สําหรับรายการที่ละเว้น ดังนั้นจำนวนรวมจึงยังคงเป็น 100

ตัวอย่างเช่น โค้ดด้านล่างจะแสดงคะแนนสูงสุดจากลีดเดอร์บอร์ด

  firebase::database::Query query =
    dbRef.GetReference("Leaders").OrderByChild("score").LimitToLast(1);

  // To get the resulting DataSnapshot either use query.GetValue() and poll the
  // future, or use query.AddValueListener() and register to handle the
  // OnValueChanged callback.

กรองตามคีย์หรือค่า

คุณสามารถใช้ StartAt(), EndAt() และ EqualTo() เพื่อเลือกจุดเริ่มต้น สิ้นสุด และจุดสมมูลที่กำหนดเองสำหรับการค้นหา ซึ่งอาจเป็นประโยชน์สำหรับการใส่เลขหน้าให้กับข้อมูลหรือค้นหารายการที่มีเด็กที่มีค่าเฉพาะ

วิธีเรียงลำดับข้อมูลข้อความค้นหา

ส่วนนี้จะอธิบายวิธีจัดเรียงข้อมูลตามวิธีการเรียงลำดับแต่ละรายการในคลาส Query

OrderByChild

เมื่อใช้ OrderByChild() ข้อมูลที่มีคีย์ย่อยที่ระบุจะเรียงลำดับดังนี้

  1. เด็กที่มีค่า null สำหรับคีย์ย่อยที่ระบุจะต้องมาก่อน
  2. เด็กที่มีค่าเป็น false สำหรับคีย์ย่อยที่ระบุจะอยู่ในลำดับถัดไป หากมีเด็กหลายคนมีค่า false ระบบจะจัดเรียงเด็กเหล่านั้นแบบพจนานุกรมตามคีย์
  3. เด็กที่มีค่าเป็น true สำหรับคีย์ย่อยที่ระบุจะอยู่ในลำดับถัดไป หากมีเด็กหลายคนมีค่า true ระบบจะจัดเรียงแบบพจนานุกรมตามคีย์
  4. เด็กที่มีค่าตัวเลขจะแสดงอยู่ถัดไปโดยเรียงลำดับจากน้อยไปหามาก หากโหนดย่อยหลายรายการมีค่าตัวเลขเหมือนกันสำหรับโหนดย่อยที่ระบุ ระบบจะจัดเรียงตามคีย์
  5. สตริงจะอยู่หลังตัวเลขและจัดเรียงแบบพจนานุกรมตามลำดับจากน้อยไปมาก หากโหนดย่อยหลายรายการมีค่าเดียวกันสำหรับโหนดย่อยที่ระบุ ระบบจะเรียงลำดับแบบพจนานุกรมตามคีย์
  6. ออบเจ็กต์อยู่ท้ายสุดและจัดเรียงแบบพจนานุกรมตามคีย์ในลำดับจากน้อยไปมาก

OrderByKey

เมื่อใช้ OrderByKey() เพื่อจัดเรียงข้อมูล ระบบจะส่งข้อมูลคืนตามลำดับคีย์จากน้อยไปมาก

  1. เด็กที่มีคีย์ซึ่งแยกวิเคราะห์ได้เป็นจำนวนเต็ม 32 บิตจะมีอยู่ก่อนแล้วโดยจัดเรียงจากน้อยไปมาก
  2. เด็กที่มีค่าสตริงเป็นคีย์ถัดไป ซึ่งจัดเรียงแบบพจนานุกรมจากน้อยไปมาก

OrderByValue

เมื่อใช้ OrderByValue() ระบบจะเรียงลำดับรายการย่อยตามค่า เกณฑ์การจัดลำดับจะเหมือนกับใน OrderByChild() ยกเว้นจะใช้ค่าของโหนดแทนค่าของคีย์ย่อยที่ระบุ

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