پایگاه داده خود را ساختار دهید

این راهنما برخی از مفاهیم کلیدی در معماری داده و بهترین شیوه ها برای ساختاردهی داده های JSON در Firebase Realtime Database شما را پوشش می دهد.

ساختن یک پایگاه داده با ساختار مناسب نیاز به کمی پیش بینی دارد. مهمتر از همه، شما باید برای چگونگی ذخیره و بازیابی داده ها برنامه ریزی کنید تا آن فرآیند تا حد امکان آسان شود.

نحوه ساختار داده ها: این یک درخت JSON است

همه داده های Firebase Realtime Database به عنوان اشیاء JSON ذخیره می شوند. می توانید پایگاه داده را به عنوان درخت JSON میزبان ابری در نظر بگیرید. برخلاف پایگاه داده SQL، هیچ جدول یا رکوردی وجود ندارد. هنگامی که داده ها را به درخت JSON اضافه می کنید، به یک گره در ساختار JSON موجود با یک کلید مرتبط تبدیل می شود. می‌توانید کلیدهای خود را مانند شناسه‌های کاربری یا نام‌های معنایی ارائه کنید، یا می‌توانید با استفاده از childByAutoId برای شما ارائه شوند.

اگر کلیدهای خود را ایجاد می‌کنید، باید دارای کد 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 Database اجازه می دهد تا داده های تودرتو تا عمق 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": { ... }
  }
}

اکنون می توان با بارگیری چند بایت در هر مکالمه، واکشی سریع ابرداده برای فهرست کردن یا نمایش اتاق ها در یک UI، فهرست اتاق ها را تکرار کرد. پیام‌ها را می‌توان به‌طور جداگانه واکشی کرد و به محض رسیدن نمایش داد، و به رابط کاربری اجازه می‌دهد پاسخگو و سریع بماند.

داده هایی ایجاد کنید که مقیاس شوند

هنگام ساخت اپلیکیشن، اغلب بهتر است زیرمجموعه ای از یک لیست را دانلود کنید. این امر به ویژه در صورتی رایج است که لیست حاوی هزاران رکورد باشد. هنگامی که این رابطه ثابت و یک جهته است، می توانید به سادگی اشیاء کودک را زیر والد لانه کنید.

گاهی اوقات، این رابطه پویاتر است، یا ممکن است لازم باشد این داده ها غیرعادی شوند. بسیاری از مواقع می‌توانید با استفاده از یک پرس و جو برای بازیابی زیرمجموعه‌ای از داده‌ها، همانطور که در Retrieve Data بحث شد، داده‌ها را غیرعادی کنید.

اما حتی این ممکن است ناکافی باشد. به عنوان مثال، یک رابطه دو طرفه بین کاربران و گروه ها را در نظر بگیرید. کاربران می توانند به یک گروه تعلق داشته باشند و گروه ها لیستی از کاربران را تشکیل می دهند. وقتی زمان تصمیم گیری فرا می رسد که یک کاربر به کدام گروه تعلق دارد، همه چیز پیچیده می شود.

چیزی که لازم است روشی زیبا برای فهرست کردن گروه‌هایی است که یک کاربر به آنها تعلق دارد و فقط داده‌های آن گروه‌ها را واکشی می‌کند. فهرستی از گروه‌ها می‌تواند در اینجا کمک زیادی کند:

// 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 را دریافت کنید، حتی زمانی که فهرست کاربران یا گروه‌ها به میلیون‌ها نفر می‌رسد یا زمانی که قوانین امنیتی Realtime Database مانع از دسترسی به برخی از سوابق می‌شوند.

این رویکرد، معکوس کردن داده‌ها با فهرست کردن شناسه‌ها به‌عنوان کلید و تنظیم مقدار روی true، بررسی یک کلید را به سادگی خواندن /users/$uid/groups/$group_id و بررسی اینکه آیا آن null است یا خیر، می‌کند. ایندکس سریعتر و کارآمدتر از پرس و جو یا اسکن داده است.

مراحل بعدی