Skip to content

Firestore Data Modeling – Chọn mô hình data hợp lý

Thú thật mà nói thì cái vấn đề này khá là confuse khi mà bạn chưa bao giờ trải nghiệm hoặc chưa tham khảo một mô hình nào cả !

Trước tiên, ngày hôm nay chúng ta sẽ tìm hiểu về 3 cách modeling data phổ biến nhất trong Firestore : Map, Sub-collection hay Root-level Collection

Đồng thời hiểu về Collection Group là gì ?

Và đừng nhầm lẫn khái niệm & cách sử dụng của Collection Group & Composite Index

Table of Contents

    Maps

    Nếu bạn đang đặt câu hỏi tại sao lại không đặt tất cả những dữ liệu vào cùng 1 Doc khi mà Doc hỗ trợ nested data đến 20 level deep

    Câu trả lời là hoàn toàn được ! Trước tiên hãy tham khảo lợi & hại của cách này nhé

    • Lợi : khi view detail à only 1 fetch
    • Hại :
      • Khi không cần cũng phải fetch 1 đống
      • Và không thể sort data ở backend mà fai xử lý ở frontend

    Bây giờ hãy nhìn vào ~ điều sau đây

    #1 : Một doc chỉ chứa maximum 1MB data

    #2 : Nếu chứa tất cả reviews vào cùng 1 doc thì không thể nào chỉ fetch only review hoặc only restaurant’s info mà loại reviews

    #3 : Không thể tách data & loại trừ dư thừa

    #4 : Bạn được tính tiền bởi số lần read & write => nếu all data in 1 doc => nhiều người cùng truy cập 1 doc, cùng write & read cùng lúc => TOANG (fail to make action, v.v.)

    #5 : Array are weird : cái này thì méo lq gì nhưng mà ý là Array type trong Firestore không thực sự là Array

    Nó là Object

    Và giải pháp để tối ưu hóa việc fetch data thừa thải là Sub-Collection

    Sub-Collection

    Sub-Collection

    *Bỏ qua cái [No Composite Index Required] đi, bây giờ chưa cần quan tâm

    Mỗi lần ta get 1 doc(Restaurant) thì nó chỉ lấy data vỏn vẹn trong đó mà thôi. Không lấy những sub-collection => Hạn chế thừa data

    • Lợi : data grow à chuyện nhỏ
    • Hại : You can’t easily delete subcollections. (no cascade) = nghĩa là : nếu xóa doc -> sub-collection vẫn còn đó

    Okay !!! Bây giờ mình đi đến cách thứ 3 trước nhé ! Chưa cần tìm hiểu lý do tại sao lại có cách thứ 3 này đâu . . . Chỉ phân tích lợi & hại thôi

    Root-Level Collection

    Thay vì là đặt sub-collection thì bây giờ mình sử dụng 1 collection riêng cho Review luôn !

    Trường hợp này giống Normalize trong SQL Database không ?

    • Lợi :
      • Best for Many-to-Many Relationship
      • Không cần Collection Group Index
    • Hại :
      • Cần Composite Index(for Order & Query with Parent’s Condition)
      • Auth Rule setup không diễn ra suôn sẽ lắm (mất đi tính thừa hưởng của nested path)

    Collection Group là gì ?

    Okay !!! Trước khi minh đi đến cách thứ 3 thì mình đặt 1 câu hỏi nhé

    Nếu bây giờ với sub-collection như này tôi muốn query tất cả ~ Review (author = ‘my_name’)

    Nếu query trong 1 Collection thì được chứ nhiều Collections cùng lúc thì không !

    Vì cơ chế Auto-Index (Field Indexing) của Firestore không hỗ trợ sao query ?

    Nhưng mà sau khi Update thì đã hỗ trợ nhưng ta phải setup cho firestore để nó biết mà TẠO MỚI indexes cho Group ~ Collection CÙNG TÊN

    *Collection chỉ cần trùng tên là được gôm vào hết 1 Group. Không phân biệt sub-collection của thằng nào cả !!!!

    Tạo Collection Group Index

    hoặc để Firestore tự tạo & send link verify cho mình. Chỉ cần chạy this & click

     var myUserId = firebase.auth().currentUser.uid;
     var myReviews = firebase.firestore().collectionGroup('reviews')
       .where('author', '==', myUserId);
     myReviews.get().then(function (querySnapshot) {
        //. . .
     })

    Khi nào nên tận dụng Root-Level Collection ?

    Trong trường hợp trên bạn thấy Sub-Collection thì phải tạo Collection Group Index (limit 200 / database) => Sử dụng Root-Level Collection không tốn 1 (Exemption) / 200 nào

    Root-Level Collection

    Nhược điểm : cần Composite Index thôi

    Sub-Collection vs Root-Level Collection

    Prefer Sub-Collection when :

    • Query Review by Restaurant(rating, published_date, most_upvotes) => Không cần composite index
    • Security Rule : khi duyệt Child mà phụ thuộc vào Parent data => Yes

    => Sử dụng khi query phụ thuộc vào Parent & ít khi nào sử dụng duyệt tất cả Collection

    Ngược lại sử dụng Root-Level

    Tóm tắt lại

    Maps : khi mà tất cả data luôn luôn được sử dụng

    Sub-Collection : Query phụ thuộc vào Parent nhiều & không cần query thru nhiều Collection

    Root-Collection : Không muốn tốn Exemption & query luôn xuyên suốt collections. Lots cases use this

    Published inFirestore

    Be First to Comment

    Leave a Reply

    Your email address will not be published. Required fields are marked *