Firestore - 如何构建提要和关注系统 [英] Firestore - how to structure a feed and follow system

查看:22
本文介绍了Firestore - 如何构建提要和关注系统的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的测试社交网络应用中使用 Firebase 实时数据库,您可以在其中关注和接收您关注的人的帖子.一个传统的社交网络.我像这样构建了我的数据库 -

用户--USER_ID_1-  - 姓名-  - 电子邮件--USER_ID_2-  - 姓名-  - 电子邮件帖子--POST_ID_1-  - 图片-  - 用户身份-  - 日期--POST_ID_2-  - 图片-  - 用户身份-  - 日期时间线--用户ID_1----POST_ID_2-  -  - 日期----POST_ID_1-  -  - 日期

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

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

  • 如果某人拥有 10,000 名关注者,则会在所有 10,000 名关注者的时间线中添加一个新帖子.
  • 如果某人发布了大量帖子,而每个新关注者都会在其时间轴中收到所有这些帖子.

这些是一些问题.

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

解决方案

我稍后看到了你的问题,但我也会尽力为你提供我能想到的最好的数据库结构.所以希望你会发现这个答案有用.

我正在考虑一个架构,其中包含 users用户关注的用户posts 的三个顶级集合:

Firestore-root|--- 用户(集合)|||--- uid(文件)|||--- 名称:用户名"|||--- 电子邮件:email@email.com"|--- 关注(合集)|||--- uid(文件)|||--- userFollowing(收藏)|||--- uid(文件)|||--- uid(文件)|--- 帖子(合集)|--- uid(文件)|--- userPosts(集合)|--- postId(文件)|||--- 标题:帖子标题"|||--- 日期:2018 年 9 月 3 日下午 6:16:58 UTC+3|--- postId(文件)|--- 标题:帖子标题"|--- 日期:2018 年 9 月 3 日下午 6:16:58 UTC+3

<块引用>

如果某人有 10,000 名关注者,则新帖子会添加到所有 10,000 名关注者的时间线中.

这完全没有问题,因为这就是在 Firestore 中更新集合的原因.根据建模 Cloud Firestore 数据库的官方文档:

<块引用>

Cloud Firestore 已针对存储大量小文档进行了优化.

这就是我将 userFollowing 添加为集合而不是作为可以容纳其他对象的简单对象/映射的原因.请记住,根据关于限制和配额的官方文档,文档的最大大小为<代码>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,您就可以轻松获取他们的所有帖子.

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

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

当您向下滚动时,加载其他 15 个用户对象并获取他们最新的三个帖子等等.除了 date,您还可以向 post 对象添加其他属性,例如喜欢、评论、分享等的数量.

<块引用>

如果某人发布了大量帖子,那么每个新关注者都会在其时间轴中收到所有这些帖子.

没办法.没有必要做这样的事情.我已经在上面解释了原因.

编辑 2019 年 5 月 20 日:

另一个优化操作的解决方案是将用户应该看到的帖子存储在该用户的文档中.

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

I was using Firebase realtime database for my test social network app in which you can just follow and receive post of people you follow. A traditional social network. I structured my database something like this-

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

I also have another node "Content" which just contained id of the all the user post. So, if "A" followed "B" than all the post id of B where added to A's Timeline. And if B posted something than it was also added to all of its follower's timeline.

Now this was my solution for realtime database but it clearly have some scalability issues

  • if someone have 10,000 followers than a new post was added to all of the 10,000 follower's Timeline.
  • If someone have large amount of posts than every new follower received all of those posts in his Timeline.

These were some of the problems.

Now, I am thinking to shift this whole thing on firestore as its been claimed "Scalable". So how should I structure my database so that problems I faced in realtime database can be eliminated in firestore.

解决方案

I've seen your question a little later but I will also try to provide you the best database structure I can think of. So hope you'll find this answer useful.

I'm thinking of a schema that has there three top-level collections for users, users that a user is following and 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.

That will be no problem at all because this is the reason the collections are ment in Firestore. According to the official documentation of modeling a Cloud Firestore database:

Cloud Firestore is optimized for storing large collections of small documents.

This is the reason I have added userFollowing as a collection and not as a simple object/map that can hold other objects. Remember, the maximum size of a document according to the official documentation regarding limits and quota is 1 MiB (1,048,576 bytes). In the case of collection, there is no limitation regarding the number of documents beneath a collection. In fact, for this kind of structure is Firestore optimized for.

So having those 10,000 followers in this manner, will work perfectly fine. Furthermore, you can query the database in such a manner that will be no need to copy anything anywhere.

As you can see, the database is pretty much denormalized allowing you to query it very simple. Let's take some example but before let's create a connection to the database and get the uid of the user using the following lines of code:

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

If you want to query the database to get all the users a user is following, you can use a get() call on the following reference:

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

So in this way, you can get all user objects a user is following. Having their uid's you can simply get all their posts.

Let's say you want to get on your timeline the latest three posts of every user. The key for solving this problem, when using very large data sets is to load the data in smaller chunks. I have explained in my answer from this post a recommended way in which you can paginate queries by combining query cursors with the limit() method. I also recommend you take a look at this video for a better understanding. So to get the latest three posts of every user, you should consider using this solution. So first you need to get the first 15 user objects that you are following and then based on their uid, to get their latest three posts. To get the latest three posts of a single user, please use the following query:

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

As you are scrolling down, load other 15 user objects and get their latest three posts and so on. Beside the date you can also add other properties to your post object, like the number of likes, comments, shares and so on.

If someone have large amount of posts than every new follower received all of those posts in his Timeline.

No way. There is no need to do something like this. I have already explained above why.

Edit May 20, 2019:

Another solution to optimize the operation in which the user should see all the recent posts of everyone he follow, is to store the posts that the user should see in a document for that user.

So if we take an example, let's say facebook, you'll need to have a document containing the facebook feed for each user. However, if there is too much data that a single document can hold (1 Mib), you need to put that data in a collection, as explained above.

这篇关于Firestore - 如何构建提要和关注系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆