我正在将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”之后,那么添加到A的时间轴的B的所有职位ID。如果B发布了一些内容,那么它也会被添加到其所有关注者的时间轴中。

现在这是我的实时数据库解决方案,但显然存在一些可伸缩性问题
  • (如果有人拥有10,000个关注者,而不是新帖子被添加到所有10,000个关注者的时间轴中)。
  • 如果某人发布的帖子数量超过每个新关注者在其时间轴中收到的所有帖子。

  • 这些是一些问题。

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

    最佳答案

    稍后我已经看到了您的问题,但我还将尝试为您提供我能想到的最佳数据库结构。因此,希望您会发现此答案有用。
    我正在考虑一种模式,该模式具有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
    

    完全没有问题,因为这就是在Firestore中修改集合的原因。根据modeling a Cloud Firestore database的官方文档:

    这就是我将userFollowing添加为集合而不是作为可以容纳其他对象的简单对象/映射的原因。请记住,根据有关limits and quota的官方文档,文档的最大大小为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,您可以简单地获取他们的所有帖子。
    假设您想在时间轴上获得每个用户的最新三篇帖子。当使用非常大的数据集时,解决此问题的关键是以较小的块加载数据。我已经从 post 的答案中解释了一种推荐的方法,您可以通过将查询游标与limit()方法结合使用来对查询进行分页。我也建议您看看此 video ,以更好地理解。因此,要获取每个用户的最新三篇文章,您应该考虑使用此解决方案。因此,首先您需要获取要关注的前15个用户对象,然后根据其uid来获取其最新的三篇文章。要获取单个用户的最新三篇帖子,请使用以下查询:
    Query query = rootRef.collection("posts/" + uid + "/userPosts").orderBy("date", Query.Direction.DESCENDING)).limit(3);
    
    向下滚动时,加载其他15个用户对象并获取其最新的三个帖子,依此类推。除了date之外,您还可以向post对象添加其他属性,例如喜欢,评论,分享等的数量。

    绝不。无需执行此类操作。我已经在上面解释了原因。
    编辑2019年5月20日:
    优化操作的一种解决方案是将用户应该看到的帖子存储在该用户的文档中,在该操作中,用户应该看到他关注的每个人的所有最新帖子。
    因此,如果我们举一个例子,比如说facebook,您将需要一个包含每个用户的facebook feed的文档。但是,如果单个文档可以容纳的数据太多(1 Mib),则需要将这些数据放入集合中,如上所述。

    07-24 09:37
    查看更多