繁体   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