- Published on
Firestore: bir vaqtning o'zida ko'plab hujjatlarni (multiple documents) yuklab olish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Nega "getDocuments(as:)" o'rnatilmagan?
Oldingi darslarda biz bitta foydalanuvchi profilini topish uchun getDocument(as: DBUser.self) dan foydalangan edik. Ushbu funksiya hujjatni topib, to'g'ridan-to'g'ri Swift modeliga o'girib (decode) berar edi.
Ammo, tasavvur qiling, siz butun bir products (mahsulotlar) kolleksiyasini tortib olmoqchisiz. Firebase kutubxonasida negadir getDocuments(as: Product.self) (ko'plikda) degan qulay funksiya yo'q! Nega? Chunki Firebase sizni ogohlantirmoqchi: "Agar sizning kolleksiyangizda 1 millionta mahsulot bo'lsa, siz hammasini bir vaqtda tortib olish orqali juda katta xarajatga (pulga) va xotira to'lib qolishiga sababchi bo'lishingiz mumkin. Shuning uchun buni o'z qo'lingiz bilan bajaring!"
Lekin bizning holatimizda, masalan 30-50 ta mahsulotni bir vaqtda ekranga chiqarishimiz kerak. Buning uchun biz Firebase'ning ushbu xatosini (yoki ataylab qilinmagan funksiyasini) o'zimiz tuzatamiz!
1. Qiyin (Standart) usul
Agar biz kutubxonani o'zgartirmasdan turib hamma mahsulotlarni tortib olmoqchi bo'lsak, kodimiz quyidagicha ko'rinish oladi:
func getAllProducts() async throws -> [Product] {
// 1. Kolleksiyadagi barcha hujjatlarni "Snapshot" ko'rinishida olish
let snapshot = try await productsCollection.getDocuments()
var products: [Product] = []
// 2. Har bir hujjatni bittalab aylanib chiqish (Loop)
for document in snapshot.documents {
// 3. Har birini alohida Decode qilish
let product = try document.data(as: Product.self)
products.append(product)
}
return products
}
Bu kod yaxshi ishlaydi. Lekin sizda nafaqat products, balki posts, comments, likes kabi kolleksiyalar ham bo'lsa, har biri uchun xuddi shu 15 qatorli kodni qayta-qayta yozaverasizmi? Yo'q, biz "Junior" emasmiz. Biz kodni "Generic" holatga o'tkazamiz!
2. Professional (Generic) usul
productsCollection obyekti turlari jihatidan Firebase'ning Query tipiga (klassiga) mansub. Shuning uchun, keling butun dasturimiz davomida barcha "Query" larga ishlaydigan bitta sehrli funksiya yaratamiz. Buning uchun Query ga Extension qo'shamiz:
import FirebaseFirestore
import FirebaseFirestoreSwift
extension Query {
// T bu yerda har qanday Codable (Decodable) bo'la oladigan model bo'lishi mumkin (masalan: Product, DBUser, Comment)
func getDocuments<T: Decodable>(as type: T.Type) async throws -> [T] {
// 1. Snapshotni olish
let snapshot = try await self.getDocuments()
// 2. For loop o'rniga zamonaviy Map (High-order function) ishlatib bitta qatorda hal qilamiz
return try snapshot.documents.map { document in
try document.data(as: T.self)
}
}
}
TIP
Generics <T> siri: Ushbu T harfi qandaydir sirli narsa emas. U "Type" ya'ni "Istagan bitta Type" degan ma'noni bildiradi. Biz <T: Decodable> deyish orqali Swift'ga: "Bu funksiyaga faqat Decodable qilingan modellar kiritilishi mumkin" degan qoidani o'rnatdik.
Natija
Endi mahsulotlarni tortib olishdagi yuqoridagi 15 qatorli xunuk kodimiz o'rniga, har qanday kolleksiyada ishlaydigan, 1 qatorlik go'zal kodimiz bor:
func getAllProducts() async throws -> [Product] {
return try await productsCollection.getDocuments(as: Product.self)
}
// Boshqa faylda foydalanuvchilarni olish kerak bo'lsa:
func getAllUsers() async throws -> [DBUser] {
return try await usersCollection.getDocuments(as: DBUser.self)
}
Xulosa
Biz bitta Extension yozish orqali barcha Firebase kodlarimizni qanday masshtablash va takrorlanmas qilib (DRY qoidasi) yozishni o'rgandik. Lekin esingizda bo'lsin: getDocuments() bu xavfli buyruq! U kolleksiyadagi BARChA hujjatlarni yuklab oladi.
Agar kolleksiyangizda minglab hujjatlar bo'lsa, ularning orasidan o'zingizga kerakligini filtrlab, cheklov qo'yib (masalan 10 tasini) yuklab olishingiz shart. Buni Firebase'da Query (So'rovlar) deb ataymiz va bu aynan keyingi darsimizning bosh mavzusidir!