跟踪用户投票(每个主题一票,即 Reddit)

Posted

技术标签:

【中文标题】跟踪用户投票(每个主题一票,即 Reddit)【英文标题】:Keeping track of user votes (one vote per topic i.e 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 中一起创建一个新节点外,这几乎可以满足它的需要。

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

【问题讨论】:

【参考方案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。

【讨论】:

以上是关于跟踪用户投票(每个主题一票,即 Reddit)的主要内容,如果未能解决你的问题,请参考以下文章

在网站上存储/跟踪用户活动 [关闭]

EOS源码分析投票系统

2016新版男神女神微信吸粉投票投票源码

会话跟踪

使用ip地址跟踪访问者,有没有更好的方法? (使用 Flask 微框架)

跟踪 Firebase 上 iOS 应用的损耗