دریافت یک مرجع پایگاه داده FIR
برای خواندن یا نوشتن دادهها از پایگاه داده، به یک نمونه از FIRDatabaseReference نیاز دارید:
سویفت
var ref: DatabaseReference! ref = Database.database().reference()
هدف-سی
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
فهرستهای خواندن و نوشتن
به لیستی از دادهها اضافه کنید
از متد childByAutoId برای افزودن دادهها به یک لیست در برنامههای چندکاربره استفاده کنید. متد childByAutoId هر بار که یک فرزند جدید به مرجع Firebase مشخص شده اضافه میشود، یک کلید منحصر به فرد تولید میکند. با استفاده از این کلیدهای تولید شده خودکار برای هر عنصر جدید در لیست، چندین کلاینت میتوانند فرزندان را همزمان و بدون تداخل در نوشتن، به یک مکان اضافه کنند. کلید منحصر به فرد تولید شده توسط childByAutoId بر اساس یک مهر زمانی است، بنابراین موارد لیست به طور خودکار به ترتیب زمانی مرتب میشوند.
شما میتوانید از ارجاع به دادههای جدید برگردانده شده توسط متد childByAutoId برای دریافت مقدار کلید تولید شده خودکار فرزند یا تنظیم دادهها برای فرزند استفاده کنید. فراخوانی getKey روی یک ارجاع childByAutoId کلید تولید شده خودکار را برمیگرداند.
شما میتوانید از این کلیدهای تولید شده خودکار برای سادهسازی مسطحسازی ساختار داده خود استفاده کنید. برای اطلاعات بیشتر، به مثال خروجی دادهها مراجعه کنید.
به رویدادهای فرزند گوش دهید
رویدادهای فرزند در پاسخ به عملیات خاصی که برای فرزندان یک گره از عملیاتی مانند اضافه شدن یک فرزند جدید از طریق متد childByAutoId یا بهروزرسانی یک فرزند از طریق متد updateChildValues رخ میدهد، فعال میشوند.
| نوع رویداد | کاربرد معمول |
|---|---|
FIRDataEventTypeChildAdded | بازیابی لیست آیتمها یا گوش دادن به موارد اضافه شده به لیست آیتمها. این رویداد یک بار برای هر فرزند موجود و سپس هر بار که فرزند جدیدی به مسیر مشخص شده اضافه میشود، فعال میشود. به شنونده یک snapshot حاوی دادههای فرزند جدید ارسال میشود. |
FIRDataEventTypeChildChanged | به تغییرات در موارد موجود در یک لیست گوش دهید. این رویداد هر زمان که یک گره فرزند تغییر کند، فعال میشود. این شامل هرگونه تغییر در فرزندان گره فرزند نیز میشود. تصویر لحظهای ارسال شده به شنونده رویداد، حاوی دادههای بهروزرسانی شده برای فرزند است. |
FIRDataEventTypeChildRemoved | به حذف شدن آیتمها از یک لیست گوش دهید. این رویداد زمانی فعال میشود که یک فرزند فوری حذف شود. تصویر لحظهای ارسال شده به بلوک فراخوانی شامل دادههای فرزند حذف شده است. |
FIRDataEventTypeChildMoved | به تغییرات در ترتیب آیتمها در یک لیست مرتب گوش دهید. این رویداد هر زمان که یک بهروزرسانی باعث تغییر ترتیب فرزند شود، آغاز میشود. این رویداد با دادههایی که توسط queryOrderedByChild یا queryOrderedByValue مرتب شدهاند، استفاده میشود. |
هر یک از این روشها در کنار هم میتوانند برای گوش دادن به تغییرات یک گره خاص در پایگاه داده مفید باشند. به عنوان مثال، یک برنامه وبلاگ نویسی اجتماعی ممکن است از این روشها با هم برای نظارت بر فعالیت در نظرات یک پست استفاده کند، همانطور که در زیر نشان داده شده است:
سویفت
// 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 ) })
هدف-سی
// 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 واحد برمیگرداند، که میتوانید برای دسترسی به تک تک فرزندان، آن را پیمایش کنید.
حتی وقتی فقط یک مورد منطبق برای کوئری وجود دارد، snapshot هنوز یک لیست است؛ فقط شامل یک مورد است. برای دسترسی به مورد، باید روی نتیجه حلقه بزنید:
سویفت
_commentsRef.observe(.value) { snapshot in for child in snapshot.children { ... } }
هدف-سی
[_commentsRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // Loop over children NSEnumerator *children = [snapshot children]; FIRDataSnapshot *child; while (child = [children nextObject]) { // ... } }];
این الگو میتواند زمانی مفید باشد که میخواهید همه فرزندان یک لیست را در یک عملیات واحد دریافت کنید، به جای اینکه منتظر رویدادهای اضافه شدن فرزند اضافی باشید.
مرتبسازی و فیلتر کردن دادهها
شما میتوانید از کلاس Realtime Database FIRDatabaseQuery برای بازیابی دادههای مرتبشده بر اساس کلید، مقدار یا مقدار یک فرزند استفاده کنید. همچنین میتوانید نتیجه مرتبشده را به تعداد مشخصی از نتایج یا طیف وسیعی از کلیدها یا مقادیر فیلتر کنید.
مرتبسازی دادهها
برای بازیابی دادههای مرتبشده، با مشخص کردن یکی از روشهای order-by برای تعیین نحوهی مرتبسازی نتایج شروع کنید:
| روش | کاربرد |
|---|---|
queryOrderedByKey | نتایج را بر اساس کلیدهای فرزند مرتب کنید. |
queryOrderedByValue | نتایج را بر اساس مقادیر فرزند مرتب کنید. |
queryOrderedByChild | نتایج را بر اساس مقدار یک کلید فرزند مشخص شده یا مسیر فرزند تو در تو مرتب میکند. |
شما فقط میتوانید از یک متد order-by در یک زمان استفاده کنید. فراخوانی چندین بارهی یک متد order-by در یک query باعث ایجاد خطا میشود.
مثال زیر نشان میدهد که چگونه میتوانید لیستی از برترین پستهای یک کاربر را که بر اساس تعداد ستارههایش مرتب شدهاند، بازیابی کنید:
سویفت
// My top posts by number of stars let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
هدف-سی
// My top posts by number of stars FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"] child:[super getUid]] queryOrderedByChild:@"starCount"];
این کوئری پستهای کاربر را از مسیر موجود در پایگاه داده بر اساس شناسه کاربری آنها، که بر اساس تعداد ستارههایی که هر پست دریافت کرده است، مرتب شده است، بازیابی میکند. این تکنیک استفاده از شناسهها به عنوان کلیدهای اندیس، data fan out نامیده میشود، میتوانید اطلاعات بیشتر در مورد آن را در Structure Your Database بخوانید.
فراخوانی متد 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 انجام میشود.
سویفت
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")
هدف-سی
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 دریافت میکنید تا تعداد کل روی ۱۰۰ باقی بماند.
مثال زیر نشان میدهد که چگونه یک برنامه وبلاگنویسی نمونه میتواند فهرستی از ۱۰۰ پست اخیر همه کاربران را بازیابی کند:
سویفت
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!
هدف-سی
// 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 برای انتخاب نقاط شروع، پایان و همارزی دلخواه برای پرسوجوها استفاده کنید. این میتواند برای صفحهبندی دادهها یا یافتن مواردی با فرزندانی که مقدار خاصی دارند مفید باشد.
نحوه مرتب سازی داده های پرس و جو
این بخش نحوه مرتبسازی دادهها بر اساس هر یک از متدهای order-by در کلاس FIRDatabaseQuery را توضیح میدهد.
queryOrderedByKey
هنگام استفاده از queryOrderedByKey برای مرتبسازی دادهها، دادهها بر اساس کلید به صورت صعودی مرتب میشوند.
- فرزندانی که کلیدی دارند که میتواند به عنوان یک عدد صحیح ۳۲ بیتی تجزیه شود، ابتدا به صورت صعودی مرتب میشوند.
- فرزندانی که کلیدشان یک مقدار رشتهای است، در مرحلهی بعد قرار میگیرند و به صورت لغوی و به ترتیب صعودی مرتب شدهاند.
queryOrderedByValue
هنگام استفاده از queryOrderedByValue ، فرزندان بر اساس مقدارشان مرتب میشوند. معیارهای مرتبسازی مشابه queryOrderedByChild هستند، با این تفاوت که به جای مقدار یک کلید فرزند مشخص، از مقدار گره استفاده میشود.
queryOrderedByChild
هنگام استفاده از queryOrderedByChild ، دادههایی که حاوی کلید فرزند مشخص شده هستند به صورت زیر مرتب میشوند:
- فرزندانی که مقدارشان برای کلید فرزند مشخص شده
nilاست، در اولویت قرار میگیرند. - فرزندانی که مقدار
falseبرای کلید فرزند مشخص شده دارند، در مرحله بعد قرار میگیرند. اگر چندین فرزند مقدارfalseداشته باشند، بر اساس کلید به صورت لغوی مرتب میشوند. - فرزندانی که مقدار
trueبرای کلید فرزند مشخص شده دارند، در مرحله بعد قرار میگیرند. اگر چندین فرزند مقدارtrueداشته باشند، بر اساس کلید به صورت لغوی مرتب میشوند. - فرزندانی که مقدار عددی دارند، در مرحله بعد قرار میگیرند و به ترتیب صعودی مرتب میشوند. اگر چندین فرزند برای گره فرزند مشخص شده، مقدار عددی یکسانی داشته باشند، بر اساس کلید مرتب میشوند.
- رشتهها بعد از اعداد میآیند و به صورت لغوی و به ترتیب صعودی مرتب میشوند. اگر چندین فرزند برای گره فرزند مشخص شده مقدار یکسانی داشته باشند، بر اساس کلید به صورت لغوی مرتب میشوند.
- اشیاء در آخر میآیند و از نظر لغوی بر اساس کلید به ترتیب صعودی مرتب میشوند.
جدا کردن شنوندگان
ناظرها (Observer) هنگام خروج شما ViewController ، همگامسازی دادهها را بهطور خودکار متوقف نمیکنند. اگر یک ناظر (Observer) به درستی حذف نشود، همچنان به همگامسازی دادهها با حافظه محلی ادامه میدهد و هر شیء ثبتشده در closure مربوط به کنترلکننده رویداد (event handler) را حفظ خواهد کرد، که میتواند باعث نشت حافظه (memory leaks) شود. هنگامی که دیگر به یک ناظر نیازی نیست، آن را با ارسال FIRDatabaseHandle مرتبط به متد removeObserverWithHandle حذف کنید.
وقتی یک بلوک فراخوانی (callback block) به یک مرجع (reference) اضافه میکنید، یک FIRDatabaseHandle برگردانده میشود. از این دستگیرهها میتوان برای حذف بلوک فراخوانی استفاده کرد.
اگر چندین شنونده به یک ارجاع پایگاه داده اضافه شده باشد، هر شنونده هنگام وقوع یک رویداد فراخوانی میشود. برای متوقف کردن همگامسازی دادهها در آن مکان، باید با فراخوانی متد removeAllObservers ، تمام ناظران (Observers) را در آن مکان حذف کنید.
فراخوانی removeObserverWithHandle یا removeAllObservers روی یک شنونده، شنوندههای ثبتشده روی گرههای فرزند آن را بهطور خودکار حذف نمیکند؛ شما همچنین باید آن ارجاعها یا دستگیرهها را برای حذف آنها پیگیری کنید.