【问题标题】:Firebase Firestore Structure for getting un-seen trending posts - SocialFirebase Firestore 结构,用于获取不可见的热门帖子 - 社交
【发布时间】:2018-11-05 17:09:40
【问题描述】:

这是当前的样本结构

Posts(Collection)
    - post1Id : {
          viewCount : 100,
          likes     : 45,
          points    : 190,
          title     : "Title",
          postType  : image/video
          url       : FileUrl,
          createdOn : Timestamp,
          createdBy : user20Id,
          userName  : name,
          profilePic: url
      }
Users(Collection)
    - user1Id(Document):{
          postsCount : 10,
          userName  : name,
          profilePic : url
      }
        viewed(Collection)
            - post1Id(Document):{
                  viewedTime : ""
              }
                 
    - user2Id(Document)

最终目标是

  • 我需要获取当前用户未查看的帖子,并在分页中按降序排列。

有哪些可能的最佳解决方案(例如更改结构、云功能、来自客户端的多个查询)?

【问题讨论】:

  • 所以您在Users(Collection) -> user1Id(Document) -> viewed(Collection) 下仅托管用户看过的帖子,并且您希望获取用户未看过的所有帖子,对吗?
  • @AlexMamo 是的,这就是我需要的
  • 能否发一个更详细的数据库结构,更清楚地看到你的属性?
  • @AlexMamo 添加了更多详细信息
  • 对您有帮助的答案,即使这意味着您的数据库结构发生了一些变化?

标签: firebase google-cloud-firestore


【解决方案1】:

我正在研究一种解决方案,以显示热门帖子并消除用户已经看到的帖子或不良内容。处理两个查询真的很痛苦,尤其是当用户群增加时。 很难维护“已查看”集合并过滤新帖子。想象一下,有 100 万条查看过的帖子,然后过滤掉未看过的帖子。

所以我想出了一个解决方案,虽然不是很好,但仍然很酷。

这是我们的数据结构

帖子(收藏) --postid(文档)

  1. 标题。
  2. 说明。
  3. 图片。
  4. 时间戳。
  5. 优先级

这是一个包含基本细节的简单帖子结构。您可以看到我添加了一个 Priority 字段。该字段将发挥作用。

如何使用优先级。

  1. 我们应该查询以较高优先级开始并以较低优先级结束的帖子。
  2. 当用户发布新帖子时。将当前时间戳指定为默认优先级。
  3. 当用户对帖子点赞(点赞)时,将优先级提高 1 分钟(60000 毫秒)
  4. 当用户对帖子投反对票(不喜欢)时,将优先级降低 1 分钟(60000 毫秒)
  5. 您可以每 24 小时重置一次优先级。如果您今天早上开始浏览提要,您将看到过去 24 小时内的帖子。达到 24 小时持续时间后,您可以将优先级重置为当前时间。可以根据您的需要更改 24 小时限制。您可能希望每 15 分钟重置一次限制。因为每 15 分钟可能会添加 100 条新帖子。此限制将确保提要中的内容重复。

因此,当您开始滚动提要时,您将首先获得所有热门帖子,然后是优先级较低的帖子。如果您今天发布帖子并且人们开始支持它。它将获得更长的生命周期,从而压倒糟糕的内容,并且当您对其投反对票时,只要用户无法访问它,它就会下推帖子。

使用时间戳作为优先级,因为旧帖子应该随着时间的推移而失去优先级。即使是今天的热门帖子明天也应该失去优先权。

需要考虑的事项:

使用寿命可根据您的需要而有所不同。 用户群越大。你应该降低生命周期价值。因为如果今天发布的帖子得到 10,000 名用户的投票,那么它在未来 6.9 天的趋势是。如果有超过 100 个帖子被超过 10,000 名用户点赞,那么在这 6.9 天内您将永远看不到新帖子。 因此,热门帖子几乎不会持续一两天。

因此,在这种情况下,您可以提供 10 秒的生命周期,对于 10,000 次投票,它将提供 1.1 天的生命周期。

这不是一个完美的解决方案,但它可以帮助您入门。

【讨论】:

    【解决方案2】:

    编辑:2021 年 6 月 11 日

    现在,还有两个选项可以帮助您解决此类问题。第一个是whereNotEqualTo 方法,第二个是whereNotIn。您可以根据自己的需要选择一个或另一个。


    看到你的数据库结构,我可以说你快到了。根据您的评论,您在以下参考下托管:

    Users(Collection) -> userId(Document) -> viewed(Collection)
    

    作为文档,用户查看过的所有帖子,并且您希望获取该用户未查看过的所有帖子。因为 Firestore 中没有 !=(不等于)运算符,也没有 arrayNotContains() 函数,所以您唯一的选择是为要显示的每个帖子创建一个额外的数据库调用,并检查该特定帖子是否是是否已经看过。

    要实现这一点,首先您需要在名为postId 的帖子对象下添加另一个属性,它将以字符串形式保存实际的帖子ID。现在每次你想显示新帖子时,你应该检查帖子 id 是否已经存在于viewed 集合中。如果它不存在,请在您想要的视图中显示该帖子,否则不要。就是这样。


    编辑:根据您的 cmets:

    因此,要显示第一个帖子,它需要两次服务器调用。

    是的,要出现第一个帖子,需要两次数据库调用,一个是获取帖子,第二个是查看它是否被看到。

    大量服务器调用以获得第一篇文章。

    不,只有 两个 调用,如上所述。

    我看错了吗

    不,这就是 NoSQL 数据库的工作方式。

    还是没有其他有效的方法?

    我不知道。还有另一个选项可以使用,但适用于用户数量有限且帖子查看次数有限的应用。此选项是将用户 ID 存储在每个帖子对象的数组中,并且每次您想要显示帖子时,您只需要检查该用户 ID 是否存在于该数组中。

    但是如果一篇帖子可以被数百万用户查看,那么将数百万个 id 存储在一个数组中并不是一个好的选择,因为这种情况下的问题是文档有限制。因此,在您可以将多少数据放入文档时存在一些限制。根据usage and limits的官方文档:

    文档的最大大小:1 MiB(1,048,576 字节)

    如您所见,单个文档中的数据总量限制为 1 MiB。因此,您不能将几乎所有内容都存储在文档中。

    【讨论】:

    • 因此,要出现第一个帖子,它需要两次服务器调用作为最佳情况,并且需要大量服务器调用才能获得第一个帖子。我是看错了还是没有其他有效的方法?
    • 要回答您的新问题,请查看我的更新答案。
    • @AlexMamo 我知道实时,我只是强调您的解决方案的问题。在我看来,目前它在某些情况下并不实用。
    • @AlexMamo 我们真的不在同一个页面上,要么我说的不正确,要么你不明白我在说什么。是的,您的解决方案是最好的解决方案,我的意思是 realtimeDB 和 firestore 都不适合此用例,因为:如果用户看到前 60 个帖子,将导致 122 个查询(返回和在客户端和服务器之间来回移动),直到客户端看到一个帖子。我希望你会同意,这是不可接受的
    • @AlexMamo 我真正关心的不是价格,我不知道是什么让你这么想。我担心潜在的延迟,因为在我的个人用例中,用户不应该看到他已经看过的帖子,并且列表是排名的,所以它一直在改变顺序。对于我的用例,我认为 firestore 不会很合身。感谢您花时间理解我的观点。我只是想警告其他人潜在的问题。
    猜你喜欢
    • 2019-06-10
    • 1970-01-01
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    相关资源
    最近更新 更多