Firestore:新集合与子集合

guc*_*sch 6 database google-cloud-firestore

我正在尝试在 firestore 中组织社交媒体应用程序的数据。为帖子创建一个新集合还是将其放入用户子集合中更好?

深度应该是相同的,但是一种方式比另一种方式有什么优势吗?

创建一个新集合:

帖子(集合)>> user_id(文档)>> userposts(子集合)>> post_id(文档)>> ...

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

用户中的子集合:

用户(集合)>> user_id(文档)>> userposts(子集合)>> post_id(文档)>> ...

use*_*110 6

好吧,正如其他人提到的,您通常应该针对读取进行优化,但“优化”的含义取决于您的应用程序。如果您期望同时返回多个用户的帖子的情况很少见,那么我想将帖子放在用户下会更容易一些,这样您就可以快速获取所有帖子来自单个用户的帖子。如果你正在做一些事情,有很多不同的用户发布的常见“主题”,并且你想展示他在某个主题上发布的所有帖子,那么我猜把你的所有帖子放在一起会容易得多在单个集合中,而不必搜索多个用户集合以将所有用户关于单个主题的帖子放在一起。(尽管这实际上不再那么困难,因为能够在单个查询中跨多个集合进行搜索)

顺便说一句,需要考虑的一件事是,如果考虑到成本,将用户的所有帖子都放在单个文档中是否有意义。如果您这样做,您会读取一份文档中的所有帖子,并且 Firestore 费用主要由文档读取驱动。但是,如果您必须将许多用户关于某个“主题”的帖子汇总在一起,或者如果您有包含多个不同用户的帖子的“线程”,则这种方法可能不切实际。

回应您的评论:让我们确保我们使用相同的术语。主题是来自多个不同用户关于同一主题的多个帖子(即帖子和各种回复)。因此,如果您有一组用户,并且您有兴趣查看他们发起的所有帖子,您可以保留一个 ThreadPosts 集合,其中包含线程的发起者,并且线程中的每个帖子将包含一个 ThreadPost,您可以获得过滤最喜欢的用户发起的线程集合,然后您可以使用如下方法获取线程的帖子。

如果您想列出收藏夹参与的所有线程,那么您将获取收藏夹用户的所有帖子,对 threadId 列表进行重复数据删除,然后按 createTimestamp 顺序提取该 threadId 上的所有帖子。您可以使用 firestore 的方法来获取这些集合,这些集合既按字段值(例如“threadId”)过滤,又按字段值(例如“creationTimestamp”)排序。这里有一些代码(打字稿中的 AngularFirestore)或多或少地演示了我的意思。

 interface  ThreadPost {
   id: string;  //this is the id for this thread.
   title : string;
   originalAuthorId: string;
   creationTimestamp : number;
   lastUpdatedTimestamp: number;
 }
Run Code Online (Sandbox Code Playgroud)

然后你的帖子集合也在根,可能看起来像: [Typescript] interface Post { id: string; 作者Id:字符串线程ID:字符串postTest:字符串;创建时间戳:数字;最后更新时间戳:数字;}

因此,在数据库的根目录下,您有 3 个集合:

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;
  }
Run Code Online (Sandbox Code Playgroud)

如果您想要一个线程上的所有帖子,您可以调用:

 async fetchThreadPosts(threadId) : Post[] {
     return getFilteredOrderedCollection("posts", "threadId", ${threadId}, 
     "creationTimeStamp") 
  }
Run Code Online (Sandbox Code Playgroud)