【问题标题】:Keeping track of user votes (one vote per topic i.e Reddit)跟踪用户投票(每个主题一票,即 Reddit)
【发布时间】:2018-07-01 17:02:42
【问题描述】:

我正在开发一个应用程序,该应用程序允许用户影响实时棋盘上的球员排名和趋势(梦幻足球)。

如您所见,您可以为玩家投票或投票(仅当您通过 Firebase(Google 帐户)登录并进行身份验证时)。否则,如果您未登录,则不会进行投票登记。目前运行良好。

我的问题是,让每个用户只能对玩家投票一次的最简单方法是什么。当前的实现允许对任何玩家进行无限制的赞成或反对投票。我想要它,这样我就可以投票给汤姆布雷迪,但不会再投票给他。从那时起,我只能将其更改为不投票(通过再次点击)或不投票。我看到firebase中有用户UID,所以我可以在允许投票通过之前检查用户UID是否已经对firebase数据库中的特定玩家进行了投票,但是如果用户只是想从up改变怎么办投反对票?

这是处理投票的代码 --

downvotePlayer(playerId) {

this.state.user ?
  this.database.child(playerId).transaction(function (player) {
    if (player) {
      player.votes--
    }
    return player;
  })
  :
  console.log("Must log in to vote")

}

upvotePlayer(playerId) {
this.state.user ?
  this.database.child(playerId).transaction(function (player) {
    if (player) {
      console.log(player)
      player.votes++
    }
    return player;
  })
  :
  console.log("Must be logged in to vote.")

}

这是 Firebase 上的布局:

如果我遗漏了任何重要内容,请告诉我,我会简要介绍一下。提前致谢。


编辑:

初始数据库引用是

    this.database = firebase.database().ref().child('players');

向玩家添加投票时,我这样做:

    this.database.child(playerId).transaction(function (player) {

    if (player) {
      var ref = firebase.database().ref('players').child('voters');
      ref.child(uid).set(1);
    }

除了在 firebase 中一起创建一个新节点外,这几乎可以满足它的需要。

“选民”应该在其上方的唯一玩家内部。我的问题明显吗?感谢先生的帮助。

【问题讨论】:

    标签: reactjs firebase firebase-realtime-database


    【解决方案1】:

    对此进行建模的最简单方法是为每个玩家每个“他们可以投票的事情”存储一个计数器。例如:

    "Votes": {
      "Tom Brady": {
        "uidOfVoter1": 1,
        "uidOfVoter2": -1
      }
    }
    

    uidOfVoter 值是您为每个玩家提供的唯一值,即他们从 Firebase 身份验证中获得的 UID。在这样的结构中,每个 UID 只能出现一次。然后,您可以确保每个用户只能使用 Firebase 安全规则编写自己的投票:

    {
      "rules": {
        "Votes": {
          "$thing": {
            "$uid": {
              ".write": "auth.uid === $uid",
              ".validate": "data.isNumber() && data.val() >= -1 && data.val() <= 1"
            }
          }
        }
      }
    }
    

    现在要获得总票数:

    • 下载选票并在客户端统计。
    • 每当用户投票时更新计数器,编写安全规则以确保他们编写的投票与计数匹配。
    • 每当投票/更改投票时,使用 Cloud Functions 更新计数。

    【讨论】:

    • 感谢您的解决方案。我不确定我是否理解正确。每次用户投票时说 .. Tom Brady,firebase 会在 Brady 下添加一个带有他们 ID 的字段,它将是 -1 还是 1? Imgur Example。如果是这样,我可以看到确保每个玩家只能投票一次是多么容易。
    • 您必须为所有这些编写代码:当用户投票(赞成、中立或反对)时,您将其写入数据库。但有了这种结构和规则,他们只能为每个用户写一个“要投票的事情”一票。
    • 我很幸运目前可以访问选民的 UID。我坚持的一件事是如何构建firebase数据。目前,当我向数据库中添加一个新玩家时,它被推送为:this.database.push().set({ playerContent: playerName, votes: 0 }) 我将如何构建事物以便我推送的东西可以有子节点?如this.database.push().set({ playerContent: playerName, votes: 0, voters }),其结构如下:imgur.com/a/PncJ1(第一张图片是它当前的推送方式。)
    • 调用push()每次都会生成一个新节点,这使得很难控制某人可以投的票数。因此,不要调用push,而是使用child(uid) 为该玩家设置一票。
    • 我更新了原始帖子并进行了编辑。我认为它很接近。如果投了赞成票,它将使用 1 将 UID 设置为数据库,只是没有将其放在正确的位置。我一直在查看设置和交易的文档,并认为我只是有点偏离。我在上面的编辑中包含了它产生的代码和图像。感谢先生的帮助。
    【解决方案2】:

    布尔值。 + 为真,- 为假。 UID 的存在表示投票(r)。

    我不能说具体的编码反应,但似乎这将是代表你所追求的最简单(最好)的方式。

    一旦他们以任何一种方式投票,就禁用/灰显客户端 UI 上的相应投票按钮。即使他们破解了 UI,服务器端(数据库端)它也是一个布尔值,所以你不能为 +2 实现它。

    DB Structure
    thing
      votes
        <uid1>:true,
        <uid2>:true,
        <uid3>:false,
    

    如果用户撤消投票,只需从他们投票的事物中删除 uid。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 2017-01-14
      相关资源
      最近更新 更多