消防库 - 如何构建饲料和跟踪系统

我正在使用Firebase实时数据库进行我的测试社交网络应用程序,您可以在其中关注并接收您关注的人的帖子。传统的社交网络。我构建了我的数据库,就像这样 -

Users
--USER_ID_1
----name
----email
--USER_ID_2
----name
----email

Posts
--POST_ID_1
----image
----userid
----date
--POST_ID_2
----image
----userid
----date

Timeline
--User_ID_1
----POST_ID_2
------date
----POST_ID_1
------date

我还有另一个节点“内容”,它只包含所有用户帖子的ID。因此,如果“A”跟在“B”后面,则B的所有帖子ID都添加到A的时间轴中。如果B发布了一些东西,那么它也被添加到其所有关注者的时间轴中。

现在这是我的实时数据库解决方案,但它显然存在一些可扩展性问题

  • 如果有人有10,000个关注者,那么一个新帖子就会被添加到所有10,000个关注者的时间轴中。
  • 如果有人有大量的帖子,那么每个新关注者都会在他的时间轴上收到所有这些帖子。

这些是一些问题。

现在,我正在考虑将整个事情转移到firestore上,因为它被声称为“可扩展”。那么我应该如何构建我的数据库,以便在消防店中消除我在实时数据库中遇到的问题。


答案 1

我稍后已经看到了您的问题,但我也会尝试为您提供我能想到的最佳数据库结构。所以希望你会发现这个答案有用。

我正在考虑一个架构,它有三个顶级集合,用于和:usersusers that a user is followingposts

Firestore-root
   |
   --- users (collection)
   |     |
   |     --- uid (documents)
   |          |
   |          --- name: "User Name"
   |          |
   |          --- email: "email@email.com"
   |
   --- following (collection)
   |      |
   |      --- uid (document)
   |           |
   |           --- userFollowing (collection)
   |                 |
   |                 --- uid (documents)
   |                 |
   |                 --- uid (documents)
   |
   --- posts (collection)
         |
         --- uid (documents)
              |
              --- userPosts (collection)
                    |
                    --- postId (documents)
                    |     |
                    |     --- title: "Post Title"
                    |     |
                    |     --- date: September 03, 2018 at 6:16:58 PM UTC+3
                    |
                    --- postId (documents)
                          |
                          --- title: "Post Title"
                          |
                          --- date: September 03, 2018 at 6:16:58 PM UTC+3

如果有人有10,000个关注者,那么一个新帖子就会被添加到所有10,000个关注者的时间轴中。

这完全没有问题,因为这是收藏品在Firestore中被提及的原因。根据对Cloud Firestore数据库进行建模的官方文档:

Cloud Firestore 针对存储大型小型文档集合进行了优化。

这就是我作为集合添加的原因,而不是作为可以容纳其他对象的简单对象/映射添加的原因。请记住,根据有关限制和配额的官方文档,文档的最大大小为 。在收集的情况下,集合下的文档数量没有限制。事实上,对于这种结构是Firestore优化的。userFollowing1 MiB (1,048,576 bytes)

因此,以这种方式拥有这10,000名追随者,将完美地工作。此外,您可以以这样的方式查询数据库,而无需在任何地方复制任何内容。

如您所见,数据库几乎是非规范化的,允许您非常简单地查询它。让我们举一些例子,但在创建与数据库的连接并使用以下代码行获取用户之前:uid

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();

如果要查询数据库以获取用户正在关注的所有用户,则可以对以下引用使用调用:get()

CollectionReference userFollowingRef = rootRef.collection("following/" + uid + "/userFollowing");

因此,通过这种方式,您可以获取用户正在关注的所有用户对象。有了他们的uid,你可以简单地得到他们所有的帖子。

假设您希望在时间线上获取每个用户的最新三个帖子。当使用非常大的数据集时,解决此问题的关键是将数据加载到较小的块中。我在这篇文章的答案中解释了一种推荐的方法,您可以通过将查询游标与该方法相结合来分页查询。我还建议您观看此视频以更好地了解。因此,要获得每个用户的最新三个帖子,您应该考虑使用此解决方案。因此,首先您需要获取您正在关注的前15个用户对象,然后基于他们的,以获取他们最新的三个帖子。要获取单个用户的最新三个帖子,请使用以下查询:limit()uid

Query query = rootRef.collection("posts/" + uid + "/userPosts").orderBy("date", Query.Direction.DESCENDING)).limit(3);

向下滚动时,加载其他15个用户对象并获取他们最新的三个帖子等。除此之外,您还可以向对象添加其他属性,例如喜欢,评论,共享等的数量。datepost

如果有人有大量的帖子,那么每个新关注者都会在他的时间轴上收到所有这些帖子。

不可能。没有必要做这样的事情。我已经在上面解释了原因。

编辑2019年5月20日:

优化操作的另一种解决方案是,用户应该看到他关注的每个人的所有最近的帖子,是将用户应该在该用户的文档中看到的帖子存储起来。

因此,如果我们举个例子,假设Facebook,您需要为每个用户提供一个包含Facebook提要的文档。但是,如果单个文档可以容纳的数据过多 (1 Mib),则需要将该数据放在集合中,如上所述。


答案 2

有两种情况

  1. 应用中的用户只有少量的关注者。

  2. 应用中的用户拥有大量关注者。如果我们要将整个关注者存储在 firestore 中单个文档的单个数组中。然后,它将达到每个文档 1 MiB 的 firestore 限制。


  1. 在第一种情况下,每个用户都必须保留一个文档,该文档将关注者的列表存储在单个数组中的单个文档中。通过使用,可以有效地管理关注者列表。当您要在时间线中发布某些内容时,您必须在发布文档中添加关注者列表。arrayUnion()arrayRemove()

    并使用下面给出的查询来获取帖子

    postCollectionRef.whereArrayContains("followers", userUid).orderBy("date");
    
  2. 在第二种情况下,您只需要根据关注者数组的大小或数量来中断用户关注文档。将数组的大小达到固定大小后,下一个关注者的 ID 必须添加到下一个文档中。第一个文档必须保留字段“hasNext”,该字段存储一个布尔值。添加新帖子时,您必须复制帖子文档,每个文档都由之前中断的关注者列表组成。我们可以进行上面给出的相同查询来获取文档。


推荐