استرجاع البيانات

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

قبل ان تبدأ

قبل أن تتمكن من استخدام Realtime Database ، تحتاج إلى:

  • قم بتسجيل مشروع Unity الخاص بك وقم بتكوينه لاستخدام Firebase.

    • إذا كان مشروع Unity الخاص بك يستخدم Firebase بالفعل، فهذا يعني أنه تم تسجيله وتكوينه بالفعل لـ Firebase.

    • إذا لم يكن لديك مشروع Unity، فيمكنك تنزيل تطبيق نموذجي .

  • أضف Firebase Unity SDK (على وجه التحديد، FirebaseDatabase.unitypackage ) إلى مشروع Unity الخاص بك.

لاحظ أن إضافة Firebase إلى مشروع Unity الخاص بك يتضمن مهام في كل من وحدة تحكم Firebase وفي مشروع Unity المفتوح (على سبيل المثال، يمكنك تنزيل ملفات تكوين Firebase من وحدة التحكم، ثم نقلها إلى مشروع Unity الخاص بك).

استرجاع البيانات

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

الحصول على مرجع قاعدة البيانات

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

using Firebase;
using Firebase.Database;
using Firebase.Extensions.TaskExtension; // for ContinueWithOnMainThread

public class MyScript: MonoBehaviour {
  void Start() {
    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

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

يمكنك استخدام أسلوب GetValueAsync لقراءة لقطة ثابتة للمحتويات في مسار معين مرة واحدة. ستحتوي نتيجة المهمة على لقطة تحتوي على كافة البيانات الموجودة في ذلك الموقع، بما في ذلك بيانات الطفل. إذا لم تكن هناك بيانات، فإن اللقطة التي تم إرجاعها تكون null .

    FirebaseDatabase.DefaultInstance
      .GetReference("Leaders")
      .GetValueAsync().ContinueWithOnMainThread(task => {
        if (task.IsFaulted) {
          // Handle the error...
        }
        else if (task.IsCompleted) {
          DataSnapshot snapshot = task.Result;
          // Do something with snapshot...
        }
      });

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

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

حدث الاستخدام النموذجي
ValueChanged اقرأ واستمع إلى التغييرات التي تطرأ على محتويات المسار بالكامل.
ChildAdded استرداد قوائم العناصر أو الاستماع للإضافات إلى قائمة العناصر. يُقترح استخدامه مع ChildChanged و ChildRemoved لمراقبة التغييرات التي تطرأ على القوائم.
ChildChanged استمع للتغييرات التي تطرأ على العناصر الموجودة في القائمة. استخدمه مع ChildAdded و ChildRemoved لمراقبة التغييرات في القوائم.
ChildRemoved استمع للعناصر التي تتم إزالتها من القائمة. استخدمه مع ChildAdded و ChildChanged لمراقبة التغييرات في القوائم.
ChildMoved استمع للتغييرات في ترتيب العناصر في القائمة المرتبة. تتبع أحداث ChildMoved دائمًا حدث ChildChanged الذي تسبب في تغيير ترتيب العنصر (استنادًا إلى أسلوب الترتيب الحالي الخاص بك).

حدث القيمة المتغيرة

يمكنك استخدام حدث ValueChanged للاشتراك في تغييرات المحتويات في مسار معين. يتم تشغيل هذا الحدث مرة واحدة عند إرفاق المستمع ومرة ​​أخرى في كل مرة تتغير فيها البيانات، بما في ذلك البيانات الفرعية. يتم تمرير رد اتصال الحدث لقطة تحتوي على كافة البيانات الموجودة في ذلك الموقع، بما في ذلك البيانات الفرعية. إذا لم تكن هناك بيانات، فإن اللقطة التي تم إرجاعها تكون null .

يوضح المثال التالي لعبة تقوم باسترداد نتائج لوحة المتصدرين من قاعدة البيانات:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

يحتوي ValueChangedEventArgs على DataSnapshot الذي يحتوي على البيانات الموجودة في الموقع المحدد في قاعدة البيانات في وقت الحدث. يؤدي استدعاء Value في لقطة إلى إرجاع Dictionary<string, object> يمثل البيانات. في حالة عدم وجود بيانات في الموقع، فإن استدعاء Value يُرجع null .

في هذا المثال، يتم فحص args.DatabaseError أيضًا لمعرفة ما إذا تم إلغاء القراءة. على سبيل المثال، يمكن إلغاء القراءة إذا لم يكن لدى العميل إذن للقراءة من موقع قاعدة بيانات Firebase. سيشير DatabaseError إلى سبب حدوث الفشل.

يمكنك لاحقًا إلغاء الاشتراك في الحدث باستخدام أي DatabaseReference له نفس المسار. تعتبر مثيلات DatabaseReference سريعة الزوال ويمكن اعتبارها وسيلة للوصول إلى أي مسار واستعلام.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged -= HandleValueChanged; // unsubscribe from ValueChanged.
    }

أحداث الطفل

يتم تشغيل الأحداث الفرعية استجابة لعمليات محددة تحدث لأبناء العقدة من عملية مثل طفل جديد يضاف من خلال طريقة Push() أو طفل يتم تحديثه من خلال طريقة UpdateChildrenAsync() . يمكن أن يكون كل واحد من هذه العناصر معًا مفيدًا للاستماع إلى التغييرات التي تطرأ على عقدة معينة في قاعدة البيانات. على سبيل المثال، قد تستخدم إحدى الألعاب هذه الأساليب معًا لمراقبة النشاط في تعليقات جلسة اللعبة، كما هو موضح أدناه:

      var ref = FirebaseDatabase.DefaultInstance
      .GetReference("GameSessionComments");

      ref.ChildAdded += HandleChildAdded;
      ref.ChildChanged += HandleChildChanged;
      ref.ChildRemoved += HandleChildRemoved;
      ref.ChildMoved += HandleChildMoved;
    }

    void HandleChildAdded(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildChanged(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildRemoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildMoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

يُستخدم الحدث ChildAdded عادةً لاسترداد قائمة العناصر الموجودة في قاعدة بيانات Firebase. يتم رفع الحدث ChildAdded مرة واحدة لكل طفل موجود ثم مرة أخرى في كل مرة تتم إضافة طفل جديد إلى المسار المحدد. يتم تمرير للمستمع لقطة تحتوي على بيانات الطفل الجديد.

يتم رفع الحدث ChildChanged في أي وقت يتم فيه تعديل العقدة التابعة. يتضمن هذا أي تعديلات على أحفاد العقدة الفرعية. يتم استخدامه عادةً بالتزامن مع الأحداث ChildAdded و ChildRemoved للاستجابة للتغييرات التي يتم إجراؤها على قائمة العناصر. تحتوي اللقطة التي تم تمريرها إلى مستمع الحدث على البيانات المحدثة للطفل.

يتم تشغيل الحدث ChildRemoved عند إزالة طفل مباشر. يتم استخدامه عادةً مع عمليات الاسترجاعات الخاصة بـ ChildAdded و ChildChanged . تحتوي اللقطة التي تم تمريرها إلى رد اتصال الحدث على بيانات الطفل الذي تمت إزالته.

يتم تشغيل الحدث ChildMoved عندما يتم رفع الحدث ChildChanged بواسطة تحديث يؤدي إلى إعادة ترتيب الطفل. يتم استخدامه مع البيانات التي تم طلبها باستخدام OrderByChild أو OrderByValue .

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

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

فرز البيانات

لاسترداد البيانات التي تم فرزها، ابدأ بتحديد إحدى طرق الترتيب حسب لتحديد كيفية ترتيب النتائج:

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

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

يوضح المثال التالي كيف يمكنك الاشتراك في لوحة صدارة النتائج مرتبة حسب النتيجة.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

يحدد هذا الاستعلام الذي عند دمجه مع مستمع حدث valuechanged، يقوم بمزامنة العميل مع لوحة المتصدرين في قاعدة البيانات، مرتبة حسب درجة كل إدخال. يمكنك قراءة المزيد حول تنظيم بياناتك بكفاءة في هيكلة قاعدة بياناتك .

يحدد استدعاء الأسلوب OrderByChild() المفتاح الفرعي لترتيب النتائج وفقًا له. وفي هذه الحالة، يتم فرز النتائج حسب قيمة "score" في كل طفل. لمزيد من المعلومات حول كيفية ترتيب أنواع البيانات الأخرى، راجع كيفية ترتيب بيانات الاستعلام .

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

لتصفية البيانات، يمكنك دمج أي من أساليب الحد أو النطاق مع أسلوب ترتيب حسب عند إنشاء استعلام.

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

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

حتى في حالة وجود تطابق واحد فقط للاستعلام، تظل اللقطة عبارة عن قائمة؛ يحتوي فقط على عنصر واحد.

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

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

مع تغير العناصر، تتلقى ردود اتصال ChildAdded للعناصر التي تدخل في الاستعلام وردود اتصال ChildRemoved للعناصر التي انسحبت منه بحيث يظل العدد الإجمالي عند 100.

على سبيل المثال، يُرجع الكود أدناه أعلى نتيجة من لوحة المتصدرين:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score").LimitToLast(1)
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

التصفية حسب المفتاح أو القيمة

يمكنك استخدام 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() ، باستثناء أن قيمة العقدة تُستخدم بدلاً من قيمة المفتاح الفرعي المحدد.