استرداد البيانات باستخدام قاعدة بيانات Firebase في الوقت الفعلي للغة C++

يتناول هذا المستند أساسيات استرداد البيانات وكيفية ترتيب بيانات Firebase وتصفيتها.

قبل البدء

تأكَّد من إعداد تطبيقك وإمكانية الوصول إلى قاعدة البيانات كما هو موضّح في دليل Get Started.

استرداد البيانات

يتم استرداد بيانات Firebase إما من خلال طلب واحد إلى GetValue() أو الربط بـ ValueListener في مرجع FirebaseDatabase. يتم استدعاء معالج قيمة المستمع مرة واحدة للحالة الأولية للبيانات ومرة أخرى في أي وقت تتغيّر فيه البيانات.

الحصول على DatabaseReference

لكتابة البيانات في قاعدة البيانات، تحتاج إلى مثيل من DatabaseReference:

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

قراءة البيانات مرة واحدة

يمكنك استخدام الطريقة GetValue() لقراءة لقطة ثابتة من المحتوى في مسار معيّن مرة واحدة. ستتضمّن نتيجة المهمة لقطة ملف شخصي تحتوي على جميع البيانات في ذلك الموقع الجغرافي، بما في ذلك بيانات الأطفال. في حال عدم توفّر بيانات، تكون الصورة المصغّرة المعروضة هي 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 للحصول على مزيد من المعلومات عن التحقّق من الأخطاء، وطرق تحديد وقت استعداد النتيجة.

الاستماع إلى الأحداث

يمكنك إضافة مستمعين للاشتراك في التغييرات التي تطرأ على البيانات:

ValueListener فئة أساسية

رد الاتصال معدّل الاستخدام
OnValueChanged قراءة التغييرات التي تتم على محتوى المسار بالكامل والاستماع إليها

OnChildListener فئة أساسية

OnChildAdded استرداد قوائم العناصر أو الاستماع إلى الإضافات إلى قائمة من العناصر. الاستخدام المقترَح مع OnChildChanged و OnChildRemoved لرصد التغييرات في القوائم
OnChildChanged الاستماع إلى التغييرات في العناصر ضمن قائمة استخدِم رمزَي OnChildAdded وOnChildRemoved لرصد التغييرات في القوائم.
OnChildRemoved استمع إلى العناصر التي تتم إزالتها من قائمة. يمكنك استخدامها مع OnChildAdded وOnChildChanged لمراقبة التغييرات في القوائم.
OnChildMoved الانتباه إلى التغييرات التي تطرأ على ترتيب العناصر في قائمة مع ترتيب تأتي طلبات OnChildMoved callback دائمًا بعد طلبات OnChildChanged callback بسبب اختلاف ترتيب العنصر (استنادًا إلى طريقة الترتيب الحالية).

فئة ValueListener

يمكنك استخدام OnValueChanged callbacks للاشتراك في التغييرات التي تطرأ على المحتوى في مسار معيّن. يتم تشغيل هذا المرجع مرة واحدة عند ربط المستمع ومرة أخرى في كل مرة تتغيّر فيها البيانات، بما في ذلك الأطفال. يتم تمرير لقطة تحتوي على جميع البيانات في هذا الموقع الجغرافي، بما في ذلك بيانات العناصر الفرعية، إلى الدالة المرجعية. في حال عدم توفّر بيانات، تكون الصورة المصغّرة المعروضة هي 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);

يتم استخدام دالة الاستدعاء OnChildAdded عادةً لاسترداد قائمة بالعناصر في قاعدة بيانات Firebase. يتمّ استدعاء دالة الاستدعاء OnChildAdded مرة واحدة لكلّ عنصر فرعي حالي، ثمّ مرة أخرى في كلّ مرّة تتمّ فيها إضافة عنصر فرعي جديد إلى المسار المحدّد. يتم تمرير لقطة تحتوي على data الطفل الجديد إلى المستمع.

ويتم استدعاء دالة الاستدعاء OnChildChanged في أي وقت يتم فيه تعديل عقدة فرعية. يتضمن ذلك أي تعديلات على العناصر التابعة للعقدة الفرعية. ويُستخدَم عادةً مع OnChildAdded وOnChildRemoved للردّ على التغييرات في قائمة العناصر. تحتوي اللقطة التي تم تمريرها إلى المستمع على البيانات المعدَّلة للعنصر الفرعي.

يتمّ تشغيل دالة الاستدعاء OnChildRemoved عند إزالة عنصر فرعي مباشر. ويتم استخدامه عادةً مع استدعاءَي OnChildAdded وOnChildChanged. تحتوي اللقطة التي يتم تمريرها إلى معاودة الاتصال على بيانات الطفل الذي تمت إزالته.

يتم تشغيل معاودة الاتصال OnChildMoved عندما يتم إجراء استدعاء OnChildChanged من خلال تعديل يؤدي إلى إعادة ترتيب الطفل. ويتم استخدامها مع البيانات التي يتم ترتيبها باستخدام OrderByChild أو OrderByValue.

فرز البيانات وتصفيتها

يمكنك استخدام فئة Realtime Database Query لاسترداد البيانات التي تم ترتيبها حسب المفتاح أو القيمة أو قيمة العنصر الفرعي. يمكنك أيضًا فلترة النتيجة المرتبطة بعدد معيّن من النتائج أو نطاق من المفاتيح أو القيم.

ترتيب البيانات

لاسترداد البيانات المفروَضة، ابدأ بتحديد إحدى طرق "الترتيب حسب" لتحديد كيفية ترتيب النتائج:

الطريقة الاستخدام
OrderByChild() ترتيب النتائج حسب قيمة مفتاح فرعي محدّد
OrderByKey() ترتيب النتائج حسب مفاتيح العناصر الفرعية
OrderByValue() ترتيب النتائج حسب القيم الثانوية

يمكنك استخدام طريقة واحدة فقط لترتيب النتائج في كل مرة. يؤدي استدعاء طريقة ترتيب بالاستناد إلى عمود معيّن مرارًا وتكرارًا في طلب البحث نفسه إلى ظهور خطأ.

يوضّح المثال التالي كيفية الاشتراك في قائمة صدارة تهدف إلى قياس الأداء بالاستناد إلى النتيجة.

  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" في كل عنصر فرعي. لمزيد من المعلومات عن كيفية ترتيب أنواع البيانات الأخرى، اطّلِع على كيفية ترتيب بيانات طلبات البحث.

تصفية البيانات

لفلترة البيانات، يمكنك دمج أيّ من طرق الحدّ أو النطاق مع طريقة order-by عند إنشاء طلب بحث.

الطريقة الاستخدام
LimitToFirst() تُستخدَم لتحديد الحد الأقصى لعدد العناصر التي سيتم عرضها من بداية القائمة المرتبة للنتائج.
LimitToLast() تتيح هذه السياسة ضبط الحد الأقصى لعدد العناصر المطلوب عرضها من نهاية قائمة النتائج المرتبة.
StartAt() عرض العناصر التي تكون أكبر من أو تساوي المفتاح أو القيمة المحدّدة استنادًا إلى طريقة الترتيب المحدّدة
EndAt() عرض العناصر التي تكون قيمتها أقل من أو مساوية للمفتاح أو القيمة المحدّدة استنادًا إلى طريقة الترتيب التي تم اختيارها
EqualTo() عرض العناصر التي تساوي المفتاح أو القيمة المحدّدة استنادًا إلى طريقة الترتيب المحدّدة

على عكس طرق "الترتيب حسب"، يمكنك دمج عدّة دوالّ حدّ أو نطاق. على سبيل المثال، يمكنك دمج الطريقتَين StartAt() وEndAt() للحدّ من النتائج إلى نطاق محدّد من القيم.

حتى في حال توفّر مطابقة واحدة فقط لطلب البحث، تظلّ اللقطة قائمة، ولكنها تحتوي على عنصر واحد فقط.

تحديد عدد النتائج

يمكنك استخدام الطريقتَين LimitToFirst() وLimitToLast() لتحديد الحد الأقصى لعدد العناصر الفرعية التي سيتم مزامنتها لطلب معاودة اتصال معيّن. على سبيل المثال، إذا كنت تستخدم LimitToFirst() لضبط حدّ أقصى يبلغ 100، لن تتلقّى في البداية سوى ما يصل إلى 100 مكالمة OnChildAdded. إذا كان لديك أقل من 100 عنصر مخزّن في قاعدة بيانات Firebase، يتم تشغيل OnChildAdded دالة استدعاء لكل عنصر.

عندما تتغيّر العناصر، تتلقّى OnChildAdded طلب استدعاء للعناصر التي تدخل في طلب البحث و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()، باستثناء أنّه يتم استخدام قيمة العقدة بدلاً من قيمة مفتاح فرعي محدّد.

الخطوات التالية