一尘不染

Firestore-如何构建提要和关注系统

java

我将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

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

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

  • 如果某人有10,000个关注者,则在10,000个关注者的时间轴中添加了新帖子。
  • 如果某人发布的帖子数量超过每个新关注者在其时间轴中收到的所有帖子。
    这些是一些问题。

现在,我正在考虑将整个事情转移到Firestore上,因为它声称是“可伸缩的”。因此,我应该如何构造数据库,以便可以在Firestore中消除我在实时数据库中遇到的问题。


阅读 397

收藏
2020-03-24

共1个答案

一尘不染

稍后我已经看到了你的问题,但我还将尝试为你提供我能想到的最佳数据库结构。因此,希望你会发现此答案有用。

我在想,有有三个顶级藏品的模式的users,users that a user is following并且posts

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经过优化,可存储大量小文件。

这就是我添加userFollowing为集合而不是作为可以容纳其他对象的简单对象/映射的原因。请记住,根据官方文档中有关限制和配额的最大文档大小为1 MiB (1,048,576 bytes)。如果是托收,则托收之下的文件数量没有限制。实际上,Firestore已针对此类结构进行了优化。

因此,以这种方式拥有这10,000个关注者将可以很好地工作。此外,你可以以无需在任何地方复制任何内容的方式查询数据库。

如你所见,数据库已被高度规范化,从而使你查询起来非常简单。让我们举个例子,但在创建与数据库的连接并uid使用以下代码行获取用户之前:

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

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

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

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

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

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

向下滚动时,加载其他15个用户对象并获取其最新的三篇文章,依此类推。除了,date你还可以向post对象添加其他属性,例如喜欢,评论,分享等的数量。

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

因此,如果我们举一个例子,比方说facebook,你将需要一个包含每个用户的facebook feed的文档。但是,如果单个文档可以容纳的数据太多(1 Mib),则需要将这些数据放入集合中,如上所述。

2020-03-24