تتناول هذه المستندات أساسيات استرداد البيانات وكيفية ترتيب بيانات 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<firebase::database::DataSnapshot> 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 دائمًا عمليات رد الاتصال
OnChildChanged بسبب تغيير ترتيب العنصر
تغيير (استنادًا إلى طريقة الترتيب الحالية). |
فئة ValueListener
يمكنك استخدام عمليات رد الاتصال OnValueChanged للاشتراك في التغييرات التي تطرأ على المحتوى في مسار معيّن. يتم تفعيل عملية رد الاتصال هذه مرة واحدة عند إرفاق أداة الاستماع ومرة أخرى في كل مرة تتغيّر فيها البيانات، بما في ذلك بيانات العناصر الفرعية. يتم تمرير لقطة إلى عملية رد الاتصال تحتوي على جميع البيانات في هذا الموقع، بما في ذلك بيانات العناصر الفرعية. إذا لم تكن هناك بيانات، ستكون اللقطة المعروضة 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<DataSnapshot> على البيانات في الموقع المحدّد
في قاعدة البيانات في وقت الحدث. يؤدي استدعاء 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);
يتم عادةً استخدام عملية رد الاتصال OnChildAdded لاسترداد قائمة بالعناصر في قاعدة بيانات Firebase. يتم استدعاء عملية رد الاتصال OnChildAdded مرة واحدة لكل عنصر فرعي حالي، ثم مرة أخرى في كل مرة تتم فيها إضافة عنصر فرعي جديد إلى المسار المحدّد. يتم تمرير لقطة إلى أداة الاستماع تحتوي على بيانات العنصر الفرعي الجديد.
يتم استدعاء عملية رد الاتصال 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"
في كل عنصر فرعي. لمزيد من المعلومات عن كيفية ترتيب أنواع البيانات الأخرى،
اطّلِع على مقالة كيفية ترتيب بيانات طلب البحث.
تصفية البيانات
لتصفية البيانات، يمكنك دمج أي من طرق الحدّ أو النطاق مع طريقة ترتيب عند إنشاء طلب بحث.
| الطريقة | الاستخدام |
|---|---|
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()، يتم ترتيب البيانات التي تحتوي على مفتاح العنصر الفرعي المحدّد على النحو التالي:
- تظهر أولاً العناصر الفرعية التي تكون قيمة مفتاح العنصر الفرعي المحدّد فيها
nullتأتي أولاً. - تظهر بعد ذلك العناصر الفرعية التي تكون قيمة مفتاح العنصر الفرعي المحدّد فيها
falseتأتي بعد ذلك. إذا كانت قيمة مفتاح العنصر الفرعي المحدّد في عدة عناصر فرعية هيfalse، يتم فرزها حسب الترتيب المعجمي حسب المفتاح. - تظهر بعد ذلك العناصر الفرعية التي تكون قيمة مفتاح العنصر الفرعي المحدّد فيها
trueتأتي بعد ذلك. إذا كانت قيمة مفتاح العنصر الفرعي المحدّد في عدة عناصر فرعية هيtrue، يتم فرزها حسب الترتيب المعجمي حسب المفتاح. - تظهر بعد ذلك العناصر الفرعية التي لها قيمة رقمية، ويتم فرزها بترتيب تصاعدي. إذا كانت قيمة مفتاح العنصر الفرعي المحدّد في عدة عناصر فرعية هي نفسها، يتم فرزها حسب المفتاح.
- تظهر السلاسل بعد الأرقام ويتم فرزها حسب الترتيب المعجمي بترتيب تصاعدي. إذا كانت قيمة مفتاح العنصر الفرعي المحدّد في عدة عناصر فرعية هي نفسها، يتم فرزها حسب الترتيب المعجمي حسب المفتاح.
- تظهر الكائنات أخيرًا ويتم فرزها حسب الترتيب المعجمي حسب المفتاح بترتيب تصاعدي.
OrderByKey
عند استخدام OrderByKey() لفرز بياناتك، يتم عرض البيانات بترتيب تصاعدي حسب المفتاح.
- تظهر أولاً العناصر الفرعية التي يمكن تحليل مفتاحها على أنّه عدد صحيح مؤلف من 32 بت، ويتم فرزها بترتيب تصاعدي.
- تظهر بعد ذلك العناصر الفرعية التي تكون قيمة مفتاحها سلسلة، ويتم فرزها حسب الترتيب المعجمي بترتيب تصاعدي.
OrderByValue
عند استخدام OrderByValue()، يتم ترتيب العناصر الفرعية حسب قيمتها. تكون معايير الترتيب هي نفسها في OrderByChild()، باستثناء أنّه يتم استخدام قيمة العقدة بدلاً من قيمة مفتاح عنصر فرعي محدّد.