التعامل مع قوائم البيانات على الويب

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

لقراءة البيانات أو كتابتها في قاعدة البيانات، تحتاج إلى مثيل من firebase.database.Reference:

Web

import { getDatabase } from "firebase/database";

const database = getDatabase();

Web

var database = firebase.database();

قوائم القراءة والكتابة

إلحاق قائمة بيانات

استخدِم الطريقة push() لإلحاق البيانات بقائمة في التطبيقات المتعددة المستخدمين. تنشئ طريقة push() مفتاحًا فريدًا في كل مرة تتم فيها إضافة عنصر فرعي جديد إلى مرجع Firebase المحدّد. باستخدام هذه المفاتيح التي يتم إنشاؤها تلقائيًا لكل عنصر جديد في القائمة، يمكن لعدة عملاء إضافة عناصر فرعية إلى الموقع الجغرافي نفسه في الوقت نفسه بدون حدوث تعارضات في الكتابة. يستند المفتاح الفريد الذي تنشئه push() إلى طابع زمني، لذا يتم ترتيب عناصر القائمة تلقائيًا حسب التسلسل الزمني.

يمكنك استخدام المرجع إلى البيانات الجديدة التي تعرضها الطريقة push() للحصول على قيمة المفتاح الذي تم إنشاؤه تلقائيًا للعنصر التابع أو لضبط بيانات العنصر التابع. تحتوي السمة .key الخاصة بمرجع push() على المفتاح الذي يتم إنشاؤه تلقائيًا.

يمكنك استخدام هذه المفاتيح التي يتم إنشاؤها تلقائيًا لتبسيط بنية بياناتك. لمزيد من المعلومات، يُرجى الاطّلاع على مثال على توزيع البيانات.

على سبيل المثال، يمكن استخدام push() لإضافة مشاركة جديدة إلى قائمة المشاركات في أحد تطبيقات التواصل الاجتماعي:

Web

import { getDatabase, ref, push, set } from "firebase/database";

// Create a new post reference with an auto-generated id
const db = getDatabase();
const postListRef = ref(db, 'posts');
const newPostRef = push(postListRef);
set(newPostRef, {
    // ...
});

Web

// Create a new post reference with an auto-generated id
var postListRef = firebase.database().ref('posts');
var newPostRef = postListRef.push();
newPostRef.set({
    // ...
});

الاستماع إلى الأحداث الثانوية

يتم تشغيل أحداث العناصر الفرعية استجابةً لعمليات معيّنة تحدث للعناصر الفرعية لعقدة من عملية مثل إضافة عنصر فرعي جديد من خلال الطريقة push() أو تعديل عنصر فرعي من خلال الطريقة update().

الحدث الاستخدام النموذجي
child_added استرداد قوائم السلع أو الاستماع إلى عمليات إضافة إلى قائمة السلع يتم تشغيل هذا الحدث مرة واحدة لكل عنصر فرعي حالي، ثم مرة أخرى في كل مرة تتم إضافة عنصر فرعي جديد إلى المسار المحدّد. يتم تمرير لقطة تحتوي على بيانات الطفل الجديد إلى المستمع.
child_changed الاستماع إلى التغييرات التي تطرأ على العناصر في قائمة يتم تشغيل هذا الحدث في كل مرة يتم فيها تعديل عقدة فرعية. ويشمل ذلك أي تعديلات على العناصر التابعة للعقدة الفرعية. تحتوي اللقطة التي تم تمريرها إلى معالج الأحداث على البيانات المعدَّلة للعنصر التابع.
child_removed الاستماع إلى الأحداث التي تتم فيها إزالة عناصر من قائمة يتم تشغيل هذا الحدث عند إزالة عنصر فرعي مباشر.تحتوي اللقطة التي تم تمريرها إلى كتلة معاودة الاتصال على بيانات العنصر الفرعي الذي تمت إزالته.
child_moved الاستماع إلى التغييرات في ترتيب العناصر في قائمة مرتبة تتّبع أحداث child_moved دائمًا حدث child_changed الذي أدّى إلى تغيير ترتيب العنصر (استنادًا إلى طريقة الترتيب الحالية).

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

Web

import { getDatabase, ref, onChildAdded, onChildChanged, onChildRemoved } from "firebase/database";

const db = getDatabase();
const commentsRef = ref(db, 'post-comments/' + postId);
onChildAdded(commentsRef, (data) => {
  addCommentElement(postElement, data.key, data.val().text, data.val().author);
});

onChildChanged(commentsRef, (data) => {
  setCommentValues(postElement, data.key, data.val().text, data.val().author);
});

onChildRemoved(commentsRef, (data) => {
  deleteComment(postElement, data.key);
});

Web

var commentsRef = firebase.database().ref('post-comments/' + postId);
commentsRef.on('child_added', (data) => {
  addCommentElement(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_changed', (data) => {
  setCommentValues(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_removed', (data) => {
  deleteComment(postElement, data.key);
});

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

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

سيؤدي ربط مراقب value بقائمة بيانات إلى عرض القائمة الكاملة للبيانات كنقطة بيانات واحدة يمكنك بعد ذلك تكرارها للوصول إلى العناصر الفردية.

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

Web

import { getDatabase, ref, onValue } from "firebase/database";

const db = getDatabase();
const dbRef = ref(db, '/a/b/c');

onValue(dbRef, (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    const childKey = childSnapshot.key;
    const childData = childSnapshot.val();
    // ...
  });
}, {
  onlyOnce: true
});

Web

ref.once('value', (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    var childKey = childSnapshot.key;
    var childData = childSnapshot.val();
    // ...
  });
});

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

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

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

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

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

الطريقة الاستخدام
orderByChild() ترتيب النتائج حسب قيمة مفتاح فرعي محدّد أو مسار فرعي متداخل
orderByKey() ترتيب النتائج حسب المفاتيح الفرعية
orderByValue() ترتيب النتائج حسب القيم الفرعية

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

يوضّح المثال التالي كيف يمكنك استرداد قائمة بأهم مشاركات المستخدمين مرتّبة حسب عدد النجوم:

Web

import { getDatabase, ref, query, orderByChild } from "firebase/database";
import { getAuth } from "firebase/auth";

const db = getDatabase();
const auth = getAuth();

const myUserId = auth.currentUser.uid;
const topUserPostsRef = query(ref(db, 'user-posts/' + myUserId), orderByChild('starCount'));

Web

var myUserId = firebase.auth().currentUser.uid;
var topUserPostsRef = firebase.database().ref('user-posts/' + myUserId).orderByChild('starCount');

يحدّد هذا الإجراء طلب بحث يتم دمجه مع معالج أحداث فرعي لمزامنة العميل مع مشاركات المستخدم من المسار في قاعدة البيانات استنادًا إلى معرّف المستخدم، ويتم ترتيبها حسب عدد النجوم التي حصلت عليها كل مشاركة. تُعرف تقنية استخدام المعرّفات كمفاتيح فهرس باسم "توزيع البيانات"، ويمكنك الاطّلاع على مزيد من المعلومات حول هذا الموضوع في مقالة تنظيم قاعدة البيانات.

يحدّد طلب الطريقة orderByChild() مفتاح العنصر الفرعي لترتيب النتائج حسبه. في هذه الحالة، يتم ترتيب المشاركات حسب قيمة العنصر الثانوي "starCount" الخاص بها. يمكن أيضًا ترتيب الاستعلامات حسب العناصر الفرعية المتداخلة، في حال توفُّر بيانات بالشكل التالي:

"posts": {
  "ts-functions": {
    "metrics": {
      "views" : 1200000,
      "likes" : 251000,
      "shares": 1200,
    },
    "title" : "Why you should use TypeScript for writing Cloud Functions",
    "author": "Doug",
  },
  "android-arch-3": {
    "metrics": {
      "views" : 900000,
      "likes" : 117000,
      "shares": 144,
    },
    "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
    "author": "Doug",
  }
},

في هذه الحالة، يمكننا ترتيب عناصر القائمة حسب القيم المتداخلة ضمن المفتاح metrics من خلال تحديد المسار النسبي إلى العنصر الثانوي المتداخل في طلب orderByChild().

Web

import { getDatabase, ref, query, orderByChild } from "firebase/database";

const db = getDatabase();
const mostViewedPosts = query(ref(db, 'posts'), orderByChild('metrics/views'));

Web

var mostViewedPosts = firebase.database().ref('posts').orderByChild('metrics/views');

لمزيد من المعلومات حول كيفية ترتيب أنواع البيانات الأخرى، راجِع المقالة كيفية ترتيب بيانات طلبات البحث.

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

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

الطريقة الاستخدام
limitToFirst() تضبط هذه السمة الحد الأقصى لعدد العناصر المطلوب عرضها من بداية القائمة المرتبة للنتائج.
limitToLast() تضبط هذه السمة الحد الأقصى لعدد العناصر المطلوب عرضها من نهاية قائمة النتائج المرتبة.
startAt() عرض العناصر الأكبر من المفتاح أو القيمة المحدّدة أو التي تساويها، وذلك استنادًا إلى طريقة الترتيب المحدّدة
startAfter() عرض السلع التي تتجاوز المفتاح أو القيمة المحدّدة استنادًا إلى طريقة الترتيب حسب التي تم اختيارها
endAt() عرض السلع التي تقلّ عن المفتاح أو القيمة المحدّدة أو تساويها، وذلك استنادًا إلى طريقة الترتيب المحدّدة
endBefore() إرجاع السلع التي تقلّ عن المفتاح أو القيمة المحدّدة استنادًا إلى طريقة الترتيب المحدّدة
equalTo() لعرض العناصر التي تساوي المفتاح أو القيمة المحدّدة، وذلك استنادًا إلى طريقة الترتيب المحدّدة.

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

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

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

عندما تتغيّر العناصر، ستتلقّى أحداث child_added للعناصر التي تدخل طلب البحث وأحداث child_removed للعناصر التي تخرج منه، وذلك لكي يظل العدد الإجمالي 100.

يوضّح المثال التالي كيف يحدّد تطبيق التدوين النموذجي طلب بحث لاسترداد قائمة بأحدث 100 مشاركة من جميع المستخدمين:

Web

import { getDatabase, ref, query, limitToLast } from "firebase/database";

const db = getDatabase();
const recentPostsRef = query(ref(db, 'posts'), limitToLast(100));

Web

var recentPostsRef = firebase.database().ref('posts').limitToLast(100);

يحدّد هذا المثال طلب بحث فقط، ولتتم مزامنة البيانات فعليًا، يجب أن يتضمّن معالج أحداث مرفقًا.

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

يمكنك استخدام startAt() وstartAfter() وendAt() وendBefore() وequalTo() لاختيار نقاط بداية ونهاية وتكافؤ عشوائية لطلبات البحث. يمكن أن يكون ذلك مفيدًا لتقسيم البيانات إلى صفحات أو العثور على عناصر تتضمّن عناصر فرعية لها قيمة معيّنة.

كيف يتم ترتيب بيانات طلب البحث؟

يوضّح هذا القسم كيفية ترتيب البيانات حسب كل طريقة من طرق الترتيب في الفئة Query.

orderByChild

عند استخدام orderByChild()، يتم ترتيب البيانات التي تحتوي على مفتاح العنصر التابع المحدّد على النحو التالي:

  1. يتم عرض الأطفال الذين لديهم قيمة null لمفتاح الطفل المحدّد أولاً.
  2. يأتي بعد ذلك الأطفال الذين لديهم القيمة false لمفتاح الطفل المحدّد. إذا كان لدى عدة عناصر فرعية القيمة false، يتم ترتيبها معجميًا حسب المفتاح.
  3. يأتي بعد ذلك الأطفال الذين لديهم القيمة true لمفتاح الطفل المحدّد. إذا كان لدى عدة عناصر فرعية القيمة true، يتم ترتيبها معجميًا حسب المفتاح.
  4. تأتي بعد ذلك العناصر الفرعية التي تتضمّن قيمة رقمية، ويتم ترتيبها بترتيب تصاعدي. إذا كان لدى عدة عناصر فرعية القيمة الرقمية نفسها لعقدة الطفل المحدّدة، يتم ترتيبها حسب المفتاح.
  5. تأتي السلاسل بعد الأرقام ويتم ترتيبها معجميًا بترتيب تصاعدي. إذا كان لدى عدة عناصر فرعية القيمة نفسها لعقدة الطفل المحدّدة، يتم ترتيبها معجميًا حسب المفتاح.
  6. تأتي الكائنات في النهاية ويتم ترتيبها معجميًا حسب المفتاح بترتيب تصاعدي.

orderByKey

عند استخدام orderByKey() لفرز بياناتك، يتم عرض البيانات بترتيب تصاعدي حسب المفتاح.

  1. يتم عرض الأطفال الذين لديهم مفتاح يمكن تحليله كعدد صحيح 32 بت أولاً، ويتم ترتيبهم بترتيب تصاعدي.
  2. يأتي بعد ذلك الأطفال الذين لديهم قيمة سلسلة كمفتاح، ويتم ترتيبهم معجميًا بترتيب تصاعدي.

orderByValue

عند استخدام orderByValue()، يتم ترتيب الأطفال حسب قيمتهم. معايير الترتيب هي نفسها الواردة في orderByChild()، باستثناء أنّه يتم استخدام قيمة العقدة بدلاً من قيمة مفتاح ثانوي محدّد.

إلغاء ربط أدوات المعالجة

تتم إزالة عمليات الاسترجاع من خلال استدعاء الطريقة off() في مرجع قاعدة بيانات Firebase.

يمكنك إزالة مستمع واحد من خلال تمريره كمعلَمة إلى off(). يؤدي استدعاء off() في الموقع الجغرافي بدون وسيطات إلى إزالة جميع المستمعين في هذا الموقع الجغرافي.

لا يؤدي استدعاء off() على أداة معالجة بيانات تابعة إلى إزالة أدوات معالجة البيانات المسجّلة على العُقد التابعة تلقائيًا، بل يجب أيضًا استدعاء off() على أي أدوات معالجة بيانات تابعة لإزالة وظيفة معاودة الاتصال.

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