简体   繁体   English

Firestore 社交媒体好友请求数据 model

[英]Firestore social media friend requests data model

I am using Firestore to build a social media app, I am wondering what is the best way to structure the data for friend requests is.我正在使用 Firestore 构建社交媒体应用程序,我想知道为好友请求构建数据的最佳方式是什么。

When a user John wants to friend request Mary and Anne, Do I create a root collection called friend_requests and add 3 documents:当用户 John 想要加好友请求 Mary 和 Anne 时,我是否创建一个名为friend_requests的根集合并添加 3 个文档:

  1. A document with John's userId as a key the value of which will be an object each for both Mary and Anne's containing their userId and the status of request (pending/accepted/declined)一个以 John 的userId为键的文档,其值将是一个 object,每个 Mary 和 Anne 都包含他们的userId和请求status (待定/接受/拒绝)
  2. A document with Mary's userId as a key and an array with an object with John's userId and status of request一个以 Mary 的userId作为键的文档和一个包含 object 的数组,其中包含 John 的userId和请求status
  3. A document with Annes's userId as a key and an array with an object with John's userId and status of request一个以 Annes 的userId作为键的文档和一个包含 object 的数组,其中包含 John 的userId和请求status

Now, when Anne and Mary accept the friend request, I delete all three documents in friend_requests collection and then:现在,当 Anne 和 Mary 接受好友请求时,我删除了friend_requests集合中的所有三个文档,然后:

  • I add a subcollection for each user (in users root collection) called friends that contains usersIds, displayNames, and photoURLs of friends that have accepted requests我为每个用户(在users根集合中)添加了一个名为friends的子集合,其中包含已接受请求的朋友的 usersIds、displayNames 和 photoURLs

or或者

  • Should I make another root collection friends that has a document for each user containing the friends information instead?我应该为每个用户创建另一个包含朋友信息的文档的根集合friends吗?

It seems like a lot of duplicate data so I'm trying to wrap my head around it and find the best and most efficient way to do it in Firestore.似乎有很多重复的数据,所以我试图围绕它寻找最好和最有效的方法来在 Firestore 中完成它。 Any advice would be much appreciated and maybe I am going about it the wrong way!任何建议将不胜感激,也许我走错了路!

While Dharmaraj's solution will certainly work, I think that there is an even simpler solution for that, that can help you reduce the number of reads a little bit.虽然 Dharmaraj 的解决方案肯定会奏效,但我认为还有一个更简单的解决方案,可以帮助您稍微减少读取次数。 So let's assume userOne sends a friend request to userTwo , and userThree sends a friend request to the userOne .所以我们假设userOneuserOne发送好友请求,而userThreeuserTwo发送好友请求。

Firestore-root
  |
  --- users (collection)
  |    |
  |    --- $userOneUid (document)
  |    |     |
  |    |     --- //User data
  |    |
  |    --- $userTwoUid (document)
  |    |     |
  |    |     --- //User data
  |    |
  |    --- $userThreeUid (document)
  |          |
  |          --- //User data
  |
  --- requests (collection)
       |
       --- $userOneUid (document)
       |     |
       |     --- ownRequests (map)
       |     |      |
       |     |      --- $userTwoUid
       |     |             |
       |     |             --- displayName: "User Two"
       |     |             |
       |     |             --- photoUrl: "https://"
       |     |             |
       |     |             --- status: "requested"
       |     |
       |     --- friendRequests (map)
       |     |      |
       |     |      --- $userThreeUid
       |     |             |
       |     |             --- displayName: "User Three"
       |     |             |
       |     |             --- photoUrl: "https://"
       |     |             |
       |     |             --- status: "requested"
       |     |
       |     --- allFriends (map)
       |            |
       |            --- //All friends
       |
       --- $userTwoUid (document)
       |     |
       |     --- friendRequests (map)
       |            |
       |            --- $userOneUid
       |                   |
       |                   --- displayName: "User One"
       |                   |
       |                   --- photoUrl: "https://"
       |                   |
       |                   --- status: "requested"
       |
       --- $userThreeUid (document)
             |
             --- ownRequests (map)
                    |
                    --- $userOneUid
                           |
                           --- displayName: "User One"
                           |
                           --- photoUrl: "https://"
                           |
                           --- status: "requested"

To have a flattened schema, instead of creating nested collections or nested maps under the User object, I have created a separate top-level collection called requests .为了有一个扁平化的模式,我没有在用户 object 下创建嵌套 collections 或嵌套映射,而是创建了一个名为requests的单独顶级集合。 Inside this collection, there will be documents that will manage the user's own requests, friend requests, and all friends.在这个集合中,将有管理用户自己的请求、好友请求和所有好友的文档。

Seeing this schema, you might think, oh, but how can I manage to add such an amount of data in a single document?看到这个架构,你可能会想,哦,但是我怎么能设法在一个文档中添加这么多的数据呢? Even if we're limited to storing up to 1 Mib of storage in a single document , when it comes to storing such simple objects, we can store pretty much.即使我们被限制在单个文档中存储最多 1 Mib 的存储空间,当涉及到存储这些简单对象时,我们也可以存储很多。 However, if you're worried about the space, then you should consider creating separate collections for each situation, ownRequests , friendRequests , and allFriends .但是,如果您担心空间,那么您应该考虑为每种情况创建单独的 collections, ownRequestsfriendRequestsallFriends In this case, for simplicity, let's assume all the data fits into a single document.在这种情况下,为简单起见,我们假设所有数据都适合单个文档。

Going forward, as you can see, we have stored the minimum data from a User object under each map, where the key is the UID and the value is represented by three fields.展望未来,如您所见,我们在每个 map 下存储了来自用户 object 的最小数据,其中键是 UID,值由三个字段表示。 In this way you can display the name and the profile photo, to clearly indicate the user who performed the friend request.通过这种方式,您可以显示姓名和头像,以清楚地表明执行好友请求的用户。

Now, when userOne sends a friend request to userTwo , there are two operations that need to be done.现在,当userOneuserTwo发送好友请求时,需要进行两个操作。 The first one would be to add userOne inside the friendRequests map of userTwo and the second one would be to add userTwo under its own ownRequests map.第一个是在userTwo 的friendRequests userTwo中添加userOne ,第二个是在自己的ownRequests userTwo下添加userTwo。

Between these two friends we have now a friend request, this means that you'll always have to make sure that you'll restrict userTwo from sending friend requests to userOne .在这两个朋友之间,我们现在有一个朋友请求,这意味着您必须始终确保限制userTwouserOne发送朋友请求。 How can you do that?你怎么能那样做? Simply by checking the existence of the $userTwoUid inside ownRequests of userOne .只需检查ownRequests的 ownRequests 中是否存在$userTwoUid userOne If you want the userOne to be able to cancel the friend request, or userTwo to reject the friend request, then simply revert the above two operations.如果希望userOne能够取消好友请求,或者userTwo拒绝好友请求,那么只需将上述两个操作还原即可。

The same rule applies in the case userThree .同样的规则适用于userThree的情况。

Regarding displaying data, if you want to show a list of your own requests, friend requests, or a list of all friends, you need to make a single database call, that costs a single read.关于显示数据,如果要显示自己的请求列表、好友请求列表或所有好友列表,则需要进行一次数据库调用,这需要一次读取。 If you however need to load more data of a user, then when you click on the user, you can perform another request and load all the data of the user, since you already know the UID.但是,如果您需要加载用户的更多数据,那么当您单击该用户时,您可以执行另一个请求并加载该用户的所有数据,因为您已经知道 UID。

When userTwo accepts the friend request from userOne , simply move their objects inside allFriends map.userTwo接受来自userOne的好友请求时,只需将他们的对象移动到allFriends map 中。 You can also go ahead and add a bannerFriends if you want, to prevent some other users from sending friend requests.您也可以提前bannerFriends并添加横幅好友,以防止其他用户发送好友请求。 Please also note, that this will also cost only a single read.另请注意,这也将只花费一次阅读。

It seems like a lot of duplicate data so I'm trying to wrap my head around it and find the best and most efficient way to do it in Firestore.似乎有很多重复的数据,所以我试图围绕它寻找最好和最有效的方法来在 Firestore 中完成它。

Denormalizing data it's a quite common practice when it comes to NoSQL databases like Firestore and for that I recommend you check my answer from the following post:对于像 Firestore 这样的 NoSQL 数据库,非规范化数据是一种非常常见的做法,为此我建议您查看以下帖子中的答案:

Where you'll also be able to see other solutions for structuring such a database.您还可以在其中看到构建此类数据库的其他解决方案。

The first approach seems to have a lot of document creations and deletions.第一种方法似乎有很多文档创建和删除。 Instead you could create a sub-collection "friends" under "users" and store a field "status".相反,您可以在“用户”下创建一个子集合“朋友”并存储一个字段“状态”。 So the structure would be:所以结构将是:

users -> {userId} -> friends -> {friendId}

When User2 sends a friend request to User1, you can add a friend sub-document under User1 and set the status field to requested along with friendId .当 User2 向 User1 发送好友请求时,您可以在 User1 下添加好友子文档,并将status字段与friendId一起设置为requested Once User1 accepts the request, just update the status to active .一旦 User1 接受请求,只需将状态更新为active This will reduce costs of that 1 delete and 1 create operations per friend request.这将减少每个好友请求的 1 次删除和 1 次创建操作的成本。

This should cover many use cases including:这应该涵盖许多用例,包括:

  1. Listing friends/friend request of a users列出用户的好友/好友请求
  2. Listing pending friend requests sent by me (a collection group query can be used if you use sub-collection)列出我发送的待处理好友请求(如果您使用子收藏,可以使用收藏组查询

You can use Firestore triggers for Cloud Functions if you need to process anything like updating database, sending a notification/e-mail, etc when the friend request has been accepted.如果您需要在接受好友请求后处理更新数据库、发送通知/电子邮件等任何事情,您可以使用Cloud Functions 的 Firestore 触发器


The friends sub-collection could be a root-level collection but in that case you'll have to add another field userId to filter of friends of a given user. friends子集合可以是根级集合,但在这种情况下,您必须添加另一个字段userId来过滤给定用户的朋友。 That doesn't make a big difference but checkout What are the benefits of using a root collection in Firestore vs. a subcollection?这并没有太大的区别,但结帐在 Firestore 中使用根集合与子集合有什么好处? for more information on that.了解更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM