Published on

Firestore sub-collections: ma'lumotlarni to'g'ri loyihalash (favorites misolida)

Authors

Qaysi arxitektura to'g'ri?

Tasavvur qiling, siz e-commerce (onlayn do'kon) ilovasini yaratyapsiz. Har bir foydalanuvchi o'ziga yoqqan mahsulotlarni "Saralanganlar" (Favorites) ro'yxatiga qo'sha olishi kerak. Buni Firebase'da qanday qilib eng to'g'ri va samarali tarzda loyihalashimiz mumkin?

1-usul: Butun mahsulotni nusxalash (Yomon usul)

Foydalanuvchi profiliga yangi favorite_products degan joy ochib, unga yoqqan mahsulotning barcha ma'lumotlarini (narxi, rasmi, nomi) nusxalab qo'yish mumkin. Muammo: Agar ertaga do'kon egasi shu mahsulotning narxini 100dan50 dan 50 ga tushirsa, hamma foydalanuvchilarning "Saralanganlar" ro'yxatida eski narx (100$) qolib ketadi (Stale data). Uni hamma foydalanuvchilarning bazasidan topib o'zgartirib chiqish esa dahshatli va qimmat jarayon.

2-usul: Faqat ID saqlash (Eng yaxshi usul)

Foydalanuvchiga faqatgina o'sha mahsulotning ID raqamini yozib qo'yamiz. Mahsulot ekranga chiqishidan oldin, uning yangi ma'lumotlarini mahsulotlar kolleksiyasidan bitta fetch qilib tortib olamiz. Shunda har doim eng yangi narx va rasm ko'rinadi.

Sub-Collection yaratish

Buning uchun biz users kolleksiyasidagi har bir foydalanuvchi hujjati ichida yana bitta yangi Ichki kolleksiya (Sub-collection) yaratamiz. Va uni favorite_products deb nomlaymiz. users -> {user_id} -> favorite_products -> {auto_id}

Ichiga quyidagi ma'lumotlarni saqlaymiz:

struct UserFavoriteProduct: Codable, Identifiable {
    let id: String // Obyektning o'z IDsi (Auto-generated)
    let productId: Int // Mahsulotning asl IDsi
    let dateCreated: Date // Qachon qo'shilgani
}

Ma'lumot qo'shish kodi:

func addUserFavoriteProduct(userId: String, productId: Int) async throws {
    // 1. Kolleksiyaga yangi hujjat (bo'sh) qo'shamiz
    let document = userCollection.document(userId).collection("favorite_products").document()
    let documentId = document.documentID

    // 2. Ichiga ma'lumotlarni kiritamiz
    let data: [String: Any] = [
        "id": documentId,
        "product_id": productId,
        "date_created": Timestamp()
    ]

    // 3. Bazaga saqlaymiz
    try await document.setData(data, merge: false)
}

Saralanganlarni o'qish (Lazy Loading siri)

Endi foydalanuvchining saralanganlarini ekranga chiqarishimiz kerak. Biz avvaliga favorite_products ichidagi hujjatlarni olamiz:

let userFavorites = try await getUserFavoriteProducts(userId: currentUserId)

Lekin, hozir bizning qo'limizda faqat product_id lar yozilgan ro'yxat bor! Asl mahsulotlarni qanday olamiz?

Ajam dasturchi: U har bir product_id uchun for-loop (sikl) aylanib, 100 ta mahsulotni birdaniga serverdan tortib oladi. Dastur esa qotib, qulab tushadi (100 ta Fetch amaliyoti bir vaqtda ketgani uchun).

Senior dasturchi: U "Lazy Loading" (yalqov yuklash) ishlatadi. SwiftUI'da List har doim ekranga qancha sig'sa (masalan 6 ta) faqat shularnigina chizadi. Shunday ekan biz asosiy ekranda serverga so'rov yubormaymiz. Biz bitta alohida ProductCellViewBuilder degan UI yaratamiz va unga faqat product_id ni uzatamiz. U UI qachonki ekranda paydo bo'lsa (onAppear), o'shandagina o'zining ichida serverdan bitta dona mahsulotni yuklab oladi.

Natijada, sizda 1000 ta saralangan bo'lsa ham, faqat ekranda ko'rinib turgan dastlabki 6 tasigina serverdan yuklanib telefon xotirasiga olinadi.

Bu usul — ma'lumotlar bazasi xarajatlarini millionlab dollarga tejashning oddiy ammo o'ta samarali yo'lidir!

Buy mea coffee