我在我的社交网络应用中使用 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,因为它声称可扩展。我应该如何构建我的数据库,以便在 Firestore 中消除这些实时数据库中的问题?
最佳答案
我稍后才看到您的问题,但我也会尝试为您提供我能想到的最佳数据库结构。所以希望你会发现这个答案很有用。
我正在考虑一个架构,其中包含三个顶级集合:users
、用户关注的用户
和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
if someone have 10,000 followers than a new post was added to all of the 10,000 follower's Timeline.
这完全没有问题,因为这就是集合在 Firestore 中的原因。根据modeling a Cloud Firestore database的官方文档:
Cloud Firestore is optimized for storing large collections of small documents.
这就是我将 userFollowing
添加为集合而不是作为可以容纳其他对象的简单对象/映射的原因。请记住,根据有关 limits and quota 的官方文档,文档的最大大小是 1 MiB(1,048,576 字节)
。在集合的情况下,集合下的文档数量没有限制。事实上,Firestore 已经针对这种结构进行了优化。
因此,以这种方式拥有这 10,000 名追随者,将非常有效。此外,您可以以无需在任何地方复制任何内容的方式查询数据库。
如您所见,数据库非常非规范化,您可以非常简单地查询它。让我们举个例子,但在创建与数据库的连接并使用以下代码行获取用户的 uid
之前:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
如果您想查询数据库以获取用户关注的所有用户,您可以在以下引用上使用 get()
调用:
CollectionReference userFollowingRef = rootRef.collection("following/" + uid + "/userFollowing");
因此,通过这种方式,您可以获得用户关注的所有用户对象。有了他们的 uid,您就可以轻松获取他们所有的帖子。
假设您想在时间轴上显示每位用户的最新三篇帖子。当使用非常大的数据集时,解决这个问题的关键是以更小的 block 加载数据。我在这个 post 的回答中已经解释过了 一种推荐的方法,您可以通过将查询游标与 limit()
方法组合来对查询进行分页。我还建议你看看这个 video 以便更好地理解。因此,要获取每个用户的最新三个帖子,您应该考虑使用此解决方案。因此,首先您需要获取您关注的前 15 个用户对象,然后根据他们的 uid
,获取他们最近的三个帖子。要获取单个用户的最新三个帖子,请使用以下查询:
Query query = rootRef.collection("posts/" + uid + "/userPosts").orderBy("date", Query.Direction.DESCENDING)).limit(3);
当您向下滚动时,加载其他 15 个用户对象并获取他们最近的三个帖子等等。除了date
,您还可以为您的post
对象添加其他属性,例如点赞数、评论数、分享数等。
If someone have large amount of posts than every new follower received all of those posts in his Timeline.
没办法。没有必要做这样的事情。我已经在上面解释了原因。
2019 年 5 月 20 日编辑:
另一个优化用户应该看到他关注的每个人的所有最近帖子的操作的解决方案是将用户应该看到的帖子存储在该用户的文档中。
因此,如果我们举个例子,比如说 facebook,您需要有一个包含每个用户的 facebook 提要的文档。但是,如果单个文档可以容纳的数据过多 (1 Mib),则需要将这些数据放入集合中,如上所述。
关于java - 如何构建提要和关注系统?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46979375/