การเรียกข้อมูลด้วยฐานข้อมูลเรียลไทม์ของ 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&ltfirebase::database::DataSnapshot&gt result =
    dbRef.GetReference("Leaders").GetValue();

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

  // 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 และจะทริกเกอร์อีกครั้งทุกครั้งที่ข้อมูล รวมถึงข้อมูลย่อย มีการเปลี่ยนแปลง ระบบจะส่งสแนปชอตที่มีข้อมูลทั้งหมดในตำแหน่งนั้น รวมถึงข้อมูลย่อยไปยัง Callback หากไม่มีข้อมูล ภาพรวมที่แสดงผลจะเป็น 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&ltfirebase::database::DataSnapshot&gt 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&ltfirebase::database::DataSnapshot&gt result =
    dbRef.GetReference("GameSessionComments").AddChildListener(listener);

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

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

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

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

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

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

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

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

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

เมื่อรายการเปลี่ยนแปลง คุณจะได้รับ Callback OnChildAdded รายการสำหรับรายการที่เข้าสู่การค้นหา และ Callback OnChildRemoved รายการสำหรับรายการที่ออกจากการค้นหา เพื่อให้จำนวนรวมยังคงอยู่ที่ 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() ยกเว้นว่าจะใช้ค่าของโหนดแทนค่าของคีย์ย่อยที่ระบุ

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