Like/Dislike Firebase 函数

Like/Dislike function for Firebase

系统本身很容易理解,但实施起来却很棘手。此外,安全原因让我思考如何做到这一点。

我正在考虑让该功能在前端 firebase 脚本中工作,只需在那里做所有事情,例如检查该用户是否已经 like/dislike 发布,如果用户点击 remove/add/switch。问题在于这种方法的安全性:用户不能创建一个新功能,它不会检查是否发布了类似的内容吗?

如果可能的话,这个系统应该如何运作?现在我的逻辑是:

Clicked like:
    locally activate/deactivate like button and remove dislike active class if on
    check docs for this user/doc like
        `1`? -> remove this doc from collection
        `0`? -> switch to `1`, because `0` is dislike
        `undefined`? -> create doc with `vote: 1`
            change (+1/-1 or +2/-2) the value of post votes fields

同样不喜欢。但是对于这样一个小功能来说,这听起来真的很复杂。也许可以在不失去安全级别的情况下使用 user/votes 发送额外的集合?或者使用 http-triggers 可能会以某种方式帮助解决这个问题?这个功能在某些 PHP 类语言上会容易得多,所以我现在很害怕。

这是我的假设。

  1. 您有一个具有唯一 ID 的 post,我们称它为 post_id
  2. 您有一个具有唯一 ID 的用户,我们称它为 user_id
  3. 有 3 种有效状态:(未定义)、(喜欢)、(不喜欢)

基本流程如下

为了存储 likes/dislikes,您创建了一个名为 feelings 的集合,它使用 post_id+':'+user_id 作为文档 ID(这很容易查找)。

feelings 中的文档有一个名为 state 的字段,其中存储 -1 表示不喜欢,1 表示喜欢。

如您所述,您可以简单地将此值设置或覆盖为用户需要的任何值。如果他们决定删除他们的 'feeling' 并且既不喜欢也不不喜欢,则发出删除命令(这比写入将状态设置为 0 更便宜)。

使用 Cloud Functions 侦听 feelings 集合并更新 post 文档 like/dislike 基于此状态如何变化(或获取 created/deleted)的计数。

安全规则只能强制执行 -11 状态,如果您使用的是 Firebase Auth,您可以简单地强制只允许匹配 user_id 的用户被能够改变状态。

你现在得到了什么?

您现在的系统具有以下属性:

  • 用户可以喜欢和不喜欢posts
  • 用户可以删除 and/or 更改他们的 like/dislikes
  • 用户只能喜欢或不喜欢一个 post 一次 - 他们不能多次这样做
  • 只有有效的状态(喜欢,不喜欢)可以写入数据库
  • 只有用户可以更新他们的likes/dislikes
  • 可扩展:无论是 10 post 秒,还是数百万 post 秒,这个系统都可以工作

奖金积分

使用您注册的相同 Cloud Functions 事件来更新计数,您还可以使用它在喜欢和不喜欢数组中的用户 ID 列表中添加或删除。这将允许您列出喜欢或不喜欢 post 的用户,而不必查询 feelings 集合

中的每个单独文档

另请记住,Cloud Functions 有很小的机会为单个事件触发多次。如果您希望保证计数准确,请使代码幂等,或者只是手动触发 'recount' 过程,您可以在您或用户检测到计数似乎相差 1 时触发。

如果有人想知道实时数据库!

var ref = firebase.database().ref(selectchapter + questionId + user_id);

ref.once("value", function (snapshot) {
            var exists = snapshot.val() !== null;
            if (!exists) {
               
                    firebase
                        .database()
                        .ref(
                            selectchapter +
                            questionId + user_id
                        )
                        .set({
                            status: 1
                        }).then(function () {
                            firebase.database().ref(q +
                                questionId + "likes").transaction(function (likes) {
                                return (likes || 0) + 1
                            });
                        });
                
            }
        });