ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

بناء قاعدة البيانات الخاصة بك

يغطي هذا الدليل بعض المفاهيم الأساسية في هندسة البيانات وأفضل الممارسات لهيكلة بيانات JSON في قاعدة بيانات Firebase Realtime.

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

طريقة تنظيم البيانات: إنها شجرة JSON

يتم تخزين جميع بيانات Firebase Realtime Database ككائنات JSON. يمكنك اعتبار قاعدة البيانات بمثابة شجرة JSON مستضافة على السحابة. على عكس قاعدة بيانات SQL ، لا توجد جداول أو سجلات. عند إضافة البيانات إلى شجرة JSON ، تصبح عقدة في بنية JSON الحالية بمفتاح مرتبط. يمكنك توفير مفاتيحك الخاصة ، مثل معرفات المستخدمين أو الأسماء الدلالية ، أو يمكن توفيرها لك باستخدام طريقة push() .

إذا قمت بإنشاء مفاتيحك الخاصة ، فيجب أن تكون بترميز UTF-8 ، ويمكن أن تكون بحد أقصى 768 بايت ، ولا يمكن أن تحتوي على . أو $ أو # أو [ أو ] أو / أو أحرف تحكم ASCII من 0 إلى 31 أو 127. ولا يمكنك استخدام أحرف تحكم ASCII في القيم نفسها أيضًا.

على سبيل المثال ، ضع في اعتبارك تطبيق دردشة يتيح للمستخدمين تخزين ملف تعريف أساسي وقائمة جهات اتصال. يوجد ملف تعريف المستخدم النموذجي في مسار ، مثل /users/$uid . قد يكون لدى المستخدم alovelace إدخال قاعدة بيانات يبدو مثل هذا:

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}

على الرغم من أن قاعدة البيانات تستخدم شجرة JSON ، يمكن تمثيل البيانات المخزنة في قاعدة البيانات على أنها أنواع أصلية معينة تتوافق مع أنواع JSON المتاحة لمساعدتك في كتابة المزيد من التعليمات البرمجية القابلة للصيانة.

أفضل الممارسات لبنية البيانات

تجنب تداخل البيانات

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

للحصول على مثال عن سبب سوء البيانات المتداخلة ، ضع في الاعتبار البنية المتداخلة التالية:

{
  // This is a poorly nested data architecture, because iterating the children
  // of the "chats" node to get a list of conversation titles requires
  // potentially downloading hundreds of megabytes of messages
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "messages": {
        "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
        "m2": { ... },
        // a very long list of messages
      }
    },
    "two": { ... }
  }
}

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

تسوية هياكل البيانات

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

{
  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },

  // Messages are separate from data we may want to iterate quickly
  // but still easily paginated and queried, and organized by chat
  // conversation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  }
}

من الممكن الآن التكرار من خلال قائمة الغرف من خلال تنزيل وحدات بايت قليلة فقط لكل محادثة ، وجلب البيانات الوصفية بسرعة لإدراج الغرف أو عرضها في واجهة المستخدم. يمكن جلب الرسائل بشكل منفصل وعرضها عند وصولها ، مما يسمح لواجهة المستخدم بالبقاء سريع الاستجابة.

إنشاء بيانات قابلة للقياس

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

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

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

المطلوب هو طريقة أنيقة لسرد المجموعات التي ينتمي إليها المستخدم وجلب البيانات فقط لتلك المجموعات. يمكن أن يساعد فهرس المجموعات كثيرًا هنا:

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

قد تلاحظ أن هذا يكرر بعض البيانات عن طريق تخزين العلاقة تحت كل من سجل Ada وتحت المجموعة. الآن يتم فهرسة alovelace تحت مجموعة ، ويتم سرد techpioneers في ملف تعريف Ada. لذلك لحذف Ada من المجموعة ، يجب تحديثه في مكانين.

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

هذا النهج ، الذي يعكس البيانات عن طريق إدراج المعرفات كمفاتيح وتعيين القيمة على true ، يجعل التحقق من المفتاح بسيطًا مثل القراءة /users/$uid/groups/$group_id والتحقق مما إذا كان null . الفهرس أسرع وأكثر كفاءة من الاستعلام عن البيانات أو مسحها ضوئيًا.

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