簡體   English   中英

Firestore:新集合與子集合

[英]Firestore: new collection vs subcollection

我正在嘗試為 firestore 中的社交媒體應用程序組織數據。 為帖子創建一個新集合還是將其放入用戶的子集合中更好?

深度應該相同,但是一種方式比另一種方式有什么優勢嗎?

創建一個新集合:

posts(集合)>> user_id(文檔)>> userposts(子集合)>> post_id(文檔)>> ...

用戶(集合)>> [其他用戶信息...]

用戶中的子集合:

用戶(集合)>> user_id(文檔)>> userposts(子集合)>> post_id(文檔)>> ...

好吧,正如其他人所提到的,您通常應該針對讀取進行優化,但是“優化”的含義將取決於您的應用程序。 如果您希望同時返回多個用戶的帖子的情況很少見,那么我想將帖子放在用戶下會更容易一些,因此您可以快速獲取所有來自單個用戶的帖子。 如果你正在做一些事情,其中有很多不同用戶發布的共同“主題”,並且你想展示他在某個主題上發布的所有內容,那么我想把你所有的帖子都放在一起會容易得多在單個集合中,而不必搜索多個用戶 collections 以將所有用戶關於單個主題的帖子匯總在一起。 (雖然這不再那么難了,因為能夠在單個查詢中搜索多個集合)

順便說一下,如果考慮成本問題,將一個用戶的所有帖子放在一個文檔中是否有意義,需要考慮一下。 如果您這樣做,您將閱讀一個文檔中的所有帖子,並且 firestore 費用主要由文檔閱讀驅動。 但是,如果您必須將許多用戶的帖子集中到一個“主題”上,或者如果您的“線程”包含來自多個不同用戶的帖子,則這種方法可能不切實際。

回應您的評論:讓我們確保我們使用相同的術語。 線程是來自多個不同用戶的關於單個主題的多個帖子(即帖子和各種回復)。 因此,如果您有一組用戶,並且您有興趣查看他們發起的所有帖子,您可以保留一個 ThreadPosts 集合,其中包含線程的發起者並且線程中的每個帖子都包含一個 ThreadPost,您可以得到一個過濾收藏夾用戶發起的線程集合,然后您可以使用如下方法獲取線程的帖子。

如果你想列出收藏者參與的所有線程,那么你將從最喜歡的用戶那里獲取所有帖子,對 threadId 列表進行重復數據刪除,然后按 creationTimestamp 順序提取該 threadId 上的所有帖子。 您可以使用 firestore 的方法來獲取這些 collections,它們均按字段值(例如“threadId”)過濾並按字段值(例如“creationTimestamp”)排序。 這是一些代碼(打字稿中的 AngularFirestore),它們或多或少地說明了我的意思。

 interface  ThreadPost {
   id: string;  //this is the id for this thread.
   title : string;
   originalAuthorId: string;
   creationTimestamp : number;
   lastUpdatedTimestamp: number;
 }

然后你的帖子集合也在根目錄下,可能看起來像:[Typescript] interface Post { id: string; authorId:字符串 threadId:字符串 postTest:字符串; 創建時間戳:數字; lastUpdatedTimestamp: 數字; }

所以在你的數據庫的根目錄下,你有 3 個 collections:

Users Posts PostThreads

因此,如果您想按 createTimestamp 順序獲取某個用戶的所有帖子,您可以執行以下操作:

 async fetchPosts(userId) : Post[] {
    return getFilteredOrderedCollection("posts", "userId", ${userId}, "creationTimeStamp") 
 }

 async getFilteredOrderedCollection(collectionPath : string, filterField : string, 
                                     filterValue: string, orderByField: string) : any[] {
    let result: any[] = [];
    await AngularFirestore.collection(`${collectionPath}`).ref
      .where(`${filterField}`, "==", `${filterValue}`)
      .orderBy(orderByField).get()
      .then(function (snapshot) {
        snapshot.forEach(function (doc) {
          let p = doc.data()
          p.timestamp = Date.now();
          result.push(p)
        })
      })
      return result;
  }

如果你想要一個線程上的所有帖子,你可以調用:

 async fetchThreadPosts(threadId) : Post[] {
     return getFilteredOrderedCollection("posts", "threadId", ${threadId}, 
     "creationTimeStamp") 
  }

以他們認為最適合未來搜索的最簡單方式保存您的數據:

  • Cloud Firestore 中的所有查詢都經濟高效
  • 唯一影響查詢性能的是請求的文檔數量

需要考慮的主要差異

如果您將數據從現有的實時數據庫樹移動到 Cloud Firestore 文檔和 collections,請記住數據庫之間的以下主要差異可能會影響您在 Cloud Firestore 中構建數據的方式:

  • 淺層查詢在分層數據結構中提供了更大的靈活性
  • 復雜的查詢提供了更多的粒度並減少了對重復數據的需求
  • 查詢游標提供更強大的分頁
  • 交易不再需要所有數據的共同根,而且效率更高
  • 實時數據庫和 Cloud Firestore 的結算費用不同。 在許多情況下,Cloud Firestore 可能比實時數據庫更昂貴,尤其是當您依賴許多小操作時。 考慮減少對數據庫的操作次數並避免不必要的寫入。 詳細了解實時數據庫和 Cloud Firestore 之間的結算差異

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM