跟踪用户投票(每个主题一票,即 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)的主要内容,如果未能解决你的问题,请参考以下文章