کار کردن با «فهرست‌های داده» در پلاتفرم‌های Apple

دریافت FIRDatabaseReference

برای خواندن یا نوشتن داده‌ها در پایگاه داده، به نمونه‌ای از FIRDatabaseReference نیاز دارید:

Swift

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
var ref: DatabaseReference!

ref = Database.database().reference()

Objective-C

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
@property (strong, nonatomic) FIRDatabaseReference *ref;

self.ref = [[FIRDatabase database] reference];

خواندن و نوشتن فهرست‌ها

افزودن به فهرست داده‌ها

از روش childByAutoId برای افزودن داده‌ها به فهرست در برنامه‌های چندکاربری استفاده کنید. روش childByAutoId هر بار که فرزند جدیدی به مرجع Firebase مشخص‌شده اضافه می‌شود، کلید یکتایی تولید می‌کند. بااستفاده از این کلیدهای خودکار برای هر عنصر جدید در فهرست، چندین مشتری می‌توانند فرزندان را هم‌زمان و بدون تداخل نوشتن به مکان یکسانی اضافه کنند. کلید یکتای تولیدشده توسط childByAutoId براساس مُهر زمان است، بنابراین موارد فهرست به‌طور خودکار به‌ترتیب زمانی مرتب می‌شوند.

می‌توانید از مرجع داده‌های جدید برگشتی از روش childByAutoId برای دریافت مقدار کلید تولیدشده خودکار کودک یا تنظیم داده‌های کودک استفاده کنید. فراخوانی getKey در مرجع childByAutoId کلید خودکار تولیدشده را برمی‌گرداند.

می‌توانید از این کلیدهای تولیدشده به‌طور خودکار برای ساده کردن ساختار داده‌هایتان استفاده کنید. برای اطلاعات بیشتر، به مثال توزیع داده مراجعه کنید.

گوش دادن به رویدادهای فرزند

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

نوع رویداد کاربرد معمول
FIRDataEventTypeChildAdded فهرست‌های موارد را بازیابی کنید یا به موارد افزوده‌شده به فهرست موارد گوش دهید. این رویداد یک‌بار برای هر کودک موجود و سپس هر بار که کودک جدیدی به مسیر مشخص‌شده اضافه می‌شود راه‌اندازی می‌شود. یک نمای لحظه‌ای حاوی داده‌های فرزند جدید به شنونده منتقل می‌شود.
FIRDataEventTypeChildChanged برای تغییرات موارد در فهرست گوش دهید. این رویداد هر زمان که گره فرزند اصلاح شود راه‌اندازی می‌شود. این شامل هرگونه تغییر در فرزندان گره کودک می‌شود. نمای کلی که به شنونده رویداد ارسال می‌شود حاوی داده‌های به‌روزرسانی‌شده برای فرزند است.
FIRDataEventTypeChildRemoved به مواردی که از فهرست برداشته می‌شوند گوش دهید. این رویداد زمانی راه‌اندازی می‌شود که فرزند بی‌واسطه‌ای برداشته شود.نمای فوری که به بلوک تماس برگشتی ارسال می‌شود حاوی داده‌های فرزند برداشته‌شده است.
FIRDataEventTypeChildMoved به تغییرات ترتیب موارد در فهرست مرتب گوش می‌دهد. این رویداد هرگاه به‌روزرسانی باعث تغییر ترتیب فرزند شود راه‌اندازی می‌شود. این ویژگی با داده‌هایی که براساس queryOrderedByChild یا queryOrderedByValue مرتب شده‌اند استفاده می‌شود.

هریک از این موارد به‌تنهایی می‌تواند برای گوش دادن به تغییرات یک گره خاص در پایگاه داده مفید باشد. برای مثال، یک برنامه وبلاگ‌نویسی اجتماعی ممکن است از این روش‌ها به‌طور هم‌زمان برای نظارت بر فعالیت در نظرات یک پست استفاده کند، همان‌طور که در زیر نشان داده شده است:

Swift

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
// Listen for new comments in the Firebase database
commentsRef.observe(.childAdded, with: { (snapshot) -> Void in
  self.comments.append(snapshot)
  self.tableView.insertRows(
    at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)],
    with: UITableView.RowAnimation.automatic
  )
})
// Listen for deleted comments in the Firebase database
commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in
  let index = self.indexOfMessage(snapshot)
  self.comments.remove(at: index)
  self.tableView.deleteRows(
    at: [IndexPath(row: index, section: self.kSectionComments)],
    with: UITableView.RowAnimation.automatic
  )
})

Objective-C

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
// Listen for new comments in the Firebase database
[_commentsRef
              observeEventType:FIRDataEventTypeChildAdded
              withBlock:^(FIRDataSnapshot *snapshot) {
                [self.comments addObject:snapshot];
                [self.tableView insertRowsAtIndexPaths:@[
                  [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments]
                ]
                                      withRowAnimation:UITableViewRowAnimationAutomatic];
              }];
// Listen for deleted comments in the Firebase database
[_commentsRef
 observeEventType:FIRDataEventTypeChildRemoved
 withBlock:^(FIRDataSnapshot *snapshot) {
   int index = [self indexOfMessage:snapshot];
   [self.comments removeObjectAtIndex:index];
   [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]]
                         withRowAnimation:UITableViewRowAnimationAutomatic];
 }];

گوش دادن به رویدادهای مقدار

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

پیوست کردن ناظر FIRDataEventTypeValue به فهرست داده‌ها کل فهرست داده‌ها را به‌عنوان یک DataSnapshot برمی‌گرداند که سپس می‌توانید با حلقه زدن روی آن به فرزندان جداگانه دسترسی پیدا کنید.

حتی زمانی که فقط یک مورد برای پُرسمان وجود داشته باشد، همچنان فهرست است؛ فقط یک مورد دارد. برای دسترسی به مورد، باید روی نتیجه حلقه بزنید:

Swift

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

Objective-C

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
[_commentsRef
              observeEventType:FIRDataEventTypeValue
              withBlock:^(FIRDataSnapshot *snapshot) {
                // Loop over children
                NSEnumerator *children = [snapshot children];
                FIRDataSnapshot *child;
                while (child = [children nextObject]) {
                  // ...
                }
              }];

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

مرتب‌سازی و فیلتر کردن داده‌ها

می‌توانید از کلاس Realtime Database FIRDatabaseQuery برای بازیابی داده‌های مرتب‌شده براساس کلید، براساس مقدار، یا براساس مقدار فرزند استفاده کنید. همچنین می‌توانید نتیجه مرتب‌شده را به تعداد مشخصی از نتایج یا محدوده کلیدها یا مقادیر فیلتر کنید.

مرتب کردن داده‌ها

برای بازیابی داده‌های مرتب‌شده، ابتدا یکی از روش‌های مرتب‌سازی را مشخص کنید تا نحوه مرتب شدن نتایج تعیین شود:

روش کاربرد
queryOrderedByKey نتایج را براساس کلیدهای فرزند مرتب کنید.
queryOrderedByValue نتایج را براساس مقادیر فرزند مرتب کنید.
queryOrderedByChild نتایج را براساس مقدار کلید فرزند مشخص‌شده یا مسیر فرزند تودرتو مرتب کنید.

در هر زمان فقط می‌توانید از یک روش ترتیب استفاده کنید. فراخوانی چندباره روش ترتیب در یک پُرسمان باعث بروز خطا می‌شود.

مثال زیر نشان می‌دهد که چگونه می‌توانید فهرست پست‌های برتر کاربر را براساس تعداد ستاره‌های آن‌ها بازیابی کنید:

Swift

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
// My top posts by number of stars
let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")

Objective-C

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
// My top posts by number of stars
FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"]
                                      child:[super getUid]]
                                     queryOrderedByChild:@"starCount"];

این پُرسمان پست‌های کاربر را از مسیر پایگاه داده براساس شناسه کاربر او بازیابی می‌کند و آن‌ها را براساس تعداد ستاره‌هایی که هر پست دریافت کرده است مرتب می‌کند. این تکنیک استفاده از شناسه‌ها به‌عنوان کلیدهای نمایه‌گذاری، «توزیع داده» نامیده می‌شود، می‌توانید درباره آن در ساختار پایگاه داده بیشتر بخوانید.

تماس با روش queryOrderedByChild کلید فرزند را برای مرتب کردن نتایج براساس آن مشخص می‌کند. در این مثال، پست‌ها براساس مقدار عنصر فرزند "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 با مشخص کردن مسیر نسبی به فرزند تودرتو در فراخوانی queryOrderedByChild مرتب کنیم.

Swift

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

Objective-C

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
 
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];

برای اطلاعات بیشتر درباره نحوه ترتیب انواع دیگر داده‌ها، نحوه ترتیب داده‌های پُرسمان را ببینید.

درحال فیلتر کردن داده‌ها

برای فیلتر کردن داده‌ها، هنگام ساختن پُرسمان می‌توانید هریک از روش‌های محدوده یا محدودیت را با روش ترتیب براساس ترکیب کنید.

روش کاربرد
queryLimitedToFirst حداکثر تعداد مواردی را که باید از ابتدای فهرست مرتب‌شده نتایج برگردانده شود تنظیم می‌کند.
queryLimitedToLast حداکثر تعداد مواردی را که باید از انتهای فهرست مرتب‌شده نتایج برگردانده شود تنظیم می‌کند.
queryStartingAtValue موارد بزرگ‌تر یا مساوی با کلید یا مقدار مشخص‌شده را برمی‌گرداند، بسته به روش ترتیب انتخابی.
queryStartingAfterValue موارد بزرگ‌تر از کلید یا مقدار مشخص‌شده را برمی‌گرداند، بسته به روش ترتیب انتخابی.
queryEndingAtValue موارد کمتر یا مساوی با کلید یا مقدار مشخص‌شده را برمی‌گرداند، بسته به روش ترتیب انتخابی.
queryEndingBeforeValue موارد کمتر از کلید یا مقدار مشخص‌شده را برمی‌گرداند، بسته به روش ترتیب انتخابی.
queryEqualToValue موارد برابر با کلید یا مقدار مشخص‌شده را برمی‌گرداند، بسته به روش انتخاب‌شده برای مرتب‌سازی.

برخلاف روش‌های ترتیب براساس، می‌توانید چندین تابع محدوده یا محدوده را ترکیب کنید. برای مثال، می‌توانید روش‌های queryStartingAtValue و queryEndingAtValue را ترکیب کنید تا نتایج را به محدوده مشخصی از مقادیر محدود کنید.

محدود کردن تعداد نتایج

می‌توانید از روش‌های queryLimitedToFirst و queryLimitedToLast برای تنظیم حداکثر تعداد کودکانی که برای یک برگشت تماس معین همگام‌سازی می‌شوند استفاده کنید. برای مثال، اگر از queryLimitedToFirst برای تنظیم محدودیت ۱۰۰ استفاده کنید، در ابتدا فقط تا ۱۰۰ FIRDataEventTypeChildAdded تماس برگشتی دریافت می‌کنید. اگر کمتر از ۱۰۰ مورد در پایگاه داده Firebase ذخیره کرده باشید، یک FIRDataEventTypeChildAdded کاربرگ برای هر مورد اجرا می‌شود.

با تغییر موارد، FIRDataEventTypeChildAdded تماس برگشتی برای مواردی که وارد پُرسمان می‌شوند و FIRDataEventTypeChildRemoved تماس برگشتی برای مواردی که از آن خارج می‌شوند دریافت می‌کنید تا تعداد کل در ۱۰۰ باقی بماند.

مثال زیر نشان می‌دهد که یک برنامه وبلاگ‌نویسی نمونه چگونه می‌تواند فهرستی از ۱۰۰ پست اخیر همه کاربران را بازیابی کند:

Swift

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!

Objective-C

توجه: این محصول Firebase در هدف «کلیپ برنامه» دردسترس نیست.
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];

فیلتر کردن براساس کلید یا مقدار

می‌توانید از queryStartingAtValue، queryStartingAfterValue، queryEndingAtValue، queryEndingBeforeValue، و queryEqualToValue برای انتخاب نقاط شروع، پایان، و معادل خودسرانه برای پُرسمان‌ها استفاده کنید. این کار برای صفحه‌بندی داده‌ها یا یافتن مواردی با فرزندانی که مقدار خاصی دارند مفید است.

نحوه مرتب شدن داده‌های پُرسمان

این بخش توضیح می‌دهد که داده‌ها چگونه با هریک از روش‌های مرتب‌سازی در کلاس FIRDatabaseQuery مرتب می‌شوند.

queryOrderedByKey

هنگام استفاده از queryOrderedByKey برای مرتب کردن داده‌ها، داده‌ها به‌ترتیب صعودی برحسب کلید برگردانده می‌شود.

  1. کودکانی که کلیدی دارند که می‌تواند به‌عنوان عدد صحیح ۳۲ بیتی تجزیه شود، در ابتدا قرار می‌گیرند و به‌ترتیب صعودی مرتب می‌شوند.
  2. کودکانی که مقدار رشته‌ای به‌عنوان کلید دارند در مرحله بعد قرار می‌گیرند و به‌ترتیب الفبایی صعودی مرتب می‌شوند.

queryOrderedByValue

هنگام استفاده از queryOrderedByValue، کودکان براساس مقدارشان مرتب می‌شوند. معیارهای ترتیب‌بندی همانند queryOrderedByChild است، با این تفاوت که به‌جای مقدار کلید فرزند مشخص‌شده، از مقدار گره استفاده می‌شود.

queryOrderedByChild

هنگام استفاده از queryOrderedByChild، داده‌هایی که حاوی کلید فرزند مشخص‌شده است به‌صورت زیر مرتب می‌شود:

  1. کودکانی که مقدار nil برای کلید کودک مشخص‌شده دارند در ابتدا قرار می‌گیرند.
  2. کودکان با مقدار false برای کلید کودک مشخص‌شده در مرحله بعد قرار دارند. اگر چند فرزند مقدار false داشته باشند، براساس کلید به‌صورت واژه‌نامه‌ای مرتب می‌شوند.
  3. کودکان با مقدار true برای کلید کودک مشخص‌شده در مرحله بعد قرار دارند. اگر چند فرزند مقدار true داشته باشند، براساس کلید به‌صورت واژه‌نامه‌ای مرتب می‌شوند.
  4. کودکان با مقدار عددی در مرحله بعد قرار می‌گیرند و به‌ترتیب صعودی مرتب می‌شوند. اگر چندین فرزند مقدار عددی یکسانی برای گره فرزند مشخص‌شده داشته باشند، براساس کلید مرتب می‌شوند.
  5. رشته‌ها بعداز اعداد می‌آیند و به‌ترتیب صعودی براساس ترتیب واژگانی مرتب می‌شوند. اگر چند کودک مقدار یکسانی برای گره کودک مشخص‌شده داشته باشند، براساس کلید به‌ترتیب الفبایی مرتب می‌شوند.
  6. اشیا در آخر قرار می‌گیرند و براساس کلید به‌ترتیب صعودی واژه‌نامه‌ای مرتب می‌شوند.

جدا کردن شنوندگان

وقتی ViewController را ترک می‌کنید، همگام‌سازی داده‌ها برای ناظران به‌طور خودکار متوقف نمی‌شود. اگر ناظر به‌درستی برداشته نشود، همچنان داده‌ها را با حافظه محلی همگام‌سازی می‌کند و هر شیء ضبط‌شده در بستار مدیریت‌کننده رویداد را حفظ می‌کند که می‌تواند باعث نشت حافظه شود. وقتی دیگر به ناظر نیاز نیست، آن را با ارسال FIRDatabaseHandle مرتبط به متد removeObserverWithHandle بردارید.

وقتی یک بلوک تماس برگشتی به یک مرجع اضافه می‌کنید، یک FIRDatabaseHandle برگردانده می‌شود. از این نام‌های کاربری می‌توان برای برداشتن مسدودسازی تماس برگشتی استفاده کرد.

اگر چندین شنونده به مرجع پایگاه داده اضافه شده باشند، هر شنونده هنگام وقوع رویداد فراخوانده می‌شود. برای متوقف کردن همگام‌سازی داده‌ها در آن مکان، باید همه ناظران را در مکان با فراخوانی روش removeAllObservers بردارید.

تماس با removeObserverWithHandle یا removeAllObservers در یک شنونده به‌طور خودکار شنوندگان ثبت‌شده در گره‌های فرزند آن را حذف نمی‌کند؛ شما باید آن ارجاع‌ها یا دسته‌ها را نیز پیگیری کنید تا آن‌ها را حذف کنید.

مراحل بعدی