Firestore:新集合与子集合

时间:2020-07-17 21:44:21

标签: database google-cloud-firestore

我正在尝试为Firestore中的社交媒体应用组织数据。为帖子创建新收藏集或将其放入用户的子收藏集更好吗?

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

创建新集合:

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

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

用户中的子集合:

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

2 个答案:

答案 0 :(得分:1)

以最适合将来搜索的最简单方式保存数据:

  • Cloud Firestore中的所有查询均具有成本效益和速度优势
  • 影响查询性能的唯一因素是请求的文档数量

要考虑的主要差异

如果您将数据从现有的实时数据库树移动到Cloud Firestore文档和集合,请记住以下数据库之间的主要差异,这可能会影响Cloud Firestore中数据的结构:

  • 浅查询在分层数据结构中提供了更大的灵活性
  • 复杂的查询提供了更高的粒度,并减少了重复数据的需求
  • 查询游标提供更可靠的分页
  • 交易不再需要所有数据的公共根,并且效率更高
  • 实时数据库和Cloud Firestore之间的计费成本有所不同。在许多情况下,Cloud Firestore可能比实时数据库贵,尤其是在您依赖许多小型操作的情况下。考虑减少对数据库的操作数量,并避免不必要的写入。详细了解实时数据库和Cloud Firestore之间的计费差异

答案 1 :(得分:1)

好吧,就像其他人提到的那样,您通常应该针对读取进行优化,但是“优化”的含义将取决于您的应用程序。如果您希望很少有必要同时返回多个用户的帖子,那么我想将这些帖子放在该用户下面会稍微容易一些,因此您可以快速获取所有内容来自单个用户的帖子。如果您正在做某件事,很多人在上面发表一些常见的“主题”,并且您想发表他在某个主题上发表的所有文章,那么我猜将所有文章张贴起来会容易得多在单个收藏夹中,而不必搜索多个用户收藏夹以将所有用户在单个主题上的帖子汇总在一起。 (尽管具有单个查询中跨多个大学搜索的能力已经不再那么困难了

顺便说一句,一秒钟要考虑的事情是,如果出于成本考虑,将用户的所有帖子放在一个文档中是否有意义。如果这样做的话,所有的帖子都可以在一个文档中读取,而Firestore的费用很大程度上取决于文档的读取。但是,如果您必须将来自多个用户的帖子汇总到一个“主题”上,或者如果您具有来自多个不同用户的帖子的“主题”,那么这种方法将不切实际。

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

如果要列出最喜欢的参加的所有线程,那么您将从最喜欢的用户处获取所有帖子,删除重复的threadIds列表,然后拉入该threadId上的所有帖子按照creationTimestamp顺序。您可以使用firestore的方法来获取这些集合,这些集合既可以通过字段值(例如“ threadId”)进行过滤,也可以通过字段值(例如“ creationTimestamp”)进行排序。这是一些代码(打字稿中的AngularFirestore),或多或少地演示了我的意思。

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

,然后您的posts Collection也位于根目录下,可能类似于: [打字稿] 界面帖子{ id:字符串; authorId:字符串 threadId:字符串 postTest:字符串; creationTimestamp:数字; lastUpdatedTimestamp:数字; }

因此,在数据库的根目录中,您有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;
  }

如果您希望所有帖子都在一个线程中,可以调用:

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