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

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

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

واجهة برمجة التطبيقات Web modular API

import { getDatabase } from "firebase/database";

const database = getDatabase();

واجهة برمجة التطبيقات لمساحة الاسم على الويب

var database = firebase.database();

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

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

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

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

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

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

واجهة برمجة التطبيقات Web modular API

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, {
    // ...
});

واجهة برمجة التطبيقات لمساحة الاسم على الويب

// 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 modular API

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);
});

واجهة برمجة التطبيقات لمساحة الاسم على الويب

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 modular API

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
});

واجهة برمجة التطبيقات لمساحة الاسم على الويب

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

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

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

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

فرز البيانات

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

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

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

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

واجهة برمجة التطبيقات Web modular API

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'));

واجهة برمجة التطبيقات لمساحة الاسم على الويب

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 modular API

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

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

واجهة برمجة التطبيقات لمساحة الاسم على الويب

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

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

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

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

الطريقة الاستخدام
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 modular API

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

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

واجهة برمجة التطبيقات لمساحة الاسم على الويب

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() على أي مستمع طفل لإزالة رد الاتصال.

الخطوات اللاحقة