MySQL处理通过AJAX和PHP投票支持喜欢/不喜欢的系统


MySQL Processing votes for a like/dislike system via AJAX and PHP

我有一个网站,它包含一个内容投票系统。因此,我建立了一个名为votes的MySQL表,其中包含uidpidvalue列,分别对应于用户投票的UUID、帖子的基于文本的ID和投票的布尔值(01表示不喜欢和喜欢)。

我已经看到了几个类似的问题,尽管似乎没有一个直接涉及在PHP和MySQL数据库之间的通信中插入和操纵投票。大多数似乎是指数据库结构或SELECTing值。我所能找到的似乎都不是我想要的系统。

数据库和与之交互的PHP运行良好——我设置了一些页面,这些页面生成JSON,其中包含每种类型的投票量和给定用户的个人投票量。我遇到的问题是优化用户输入投票的过程——我在投票时寻找的"规则"如下:

  • 如果输入的确切投票已经存在(即给定的uidpidvalue都作为相同的记录存在),则从表中删除该投票
  • 如果该用户当前没有对此帖子进行投票,请在表中添加一个具有所有三个值的投票
  • 如果该用户对此帖子进行了投票,但投票结果相反(不喜欢而不是喜欢,反之亦然),请更新记录,使投票结果匹配

页面通过会话变量接收$currentUid,并通过GET参数接收$cid$_GET["v"](显然)。

通过在两个MySQL调用中使用PDO,我已经能够在PHP中产生这种行为(假设$con是一个通用的PDO对象):

$test = $con->prepare("SELECT * FROM `votes` WHERE uid=UNHEX(:uid) AND pid=:pid AND value=:value");
$test->bindValue(":uid", $currentUid);
$test->bindValue(":pid", $pid, PDO::PARAM_INT);
$test->bindValue(":value", $_GET["v"], PDO::PARAM_BOOL);
$test->execute();
if($test->rowCount() > 0) {
    $query = $con->prepare("DELETE FROM `votes` WHERE uid=UNHEX(:uid) AND pid=:pid AND value=:value LIMIT 1");
    $query->bindValue(":uid", $currentUid);
    $query->bindValue(":pid", $pid, PDO::PARAM_INT);
    $query->bindValue(":value", $_GET["v"], PDO::PARAM_BOOL);
    $query->execute();
} else {
    $query = $con->prepare("INSERT INTO `votes` (uid, pid, value) VALUES (UNHEX(:uid), :pid, :value) ON DUPLICATE KEY UPDATE value = :value");
    $query->bindValue(":uid", $currentUid);
    $query->bindValue(":pid", $pid, PDO::PARAM_INT);
    $query->bindValue(":value", $_GET["v"], PDO::PARAM_BOOL);
    $query->execute();
}

有没有什么方法可以通过一个更大的MySQL调用来达到同样的效果,它会以任何方式影响系统的性能?我在过去发现,使用较长的MySQL语句可能比简单地使用PHP和MySQL的混合解决方案花费更长的时间。可以假设系统将经常处理投票,因此性能在这里很重要。

目前,这个过程大约需要0.05秒(通过简单的microtime()基准测试),考虑到几个并发用户,这肯定会加起来。

谢谢你的帮助!请注意,我不是SQL语法专家,我刚刚学会了如何执行INNER JOIN,这就是我决定在这里发布的原因,就好像有一个MySQL函数正是这样做的一样,我很难找到它。

在一个mysql调用中似乎不太可能做到这一点。

第一步,删除SELECT查询,除非以后绝对需要它。您的ONDUPLICATEKEY语句将为您执行此操作。

但是DELETE是必要的。不存在ON DUPLICATE KEY DELETE语法。

但是,您可以编写一个触发器,用于AFTER INSERT并删除重复项(如果有的话)。这是一种粗糙的方法,但它将减轻PHP的负担。如果您坚决要在SINGLE查询中执行任务,请执行此操作

如果表votes上的UNIQUE约束设置为(uid, pid),那么ON DUPLICATE KEY UPDATE就是您所需要的如果您将考虑在value中使用三元ENUM---+1,0,-1--来表示"喜欢"、"没有意见"answers"不喜欢"。

在给定的(uid, pid)组合没有投票的情况下,INSERT ... ON DUPLICATE KEY UPDATE将插入所提供的值。如果存在投票,并且用户希望收回否决票(从-1到0)、收回赞成票(从1到0)或应用否决票或赞成票(0到1或-1),INSERT ... ON DUPLICATE KEY UPDATE将更新记录。

使用这种方法,删除投票的唯一原因是级联操作,例如删除帖子或用户记录。我敢打赌,你可能有一些应用程序代码,可以将布尔TRUE转换为Integer+1,将布尔FALSE转换为-1。作为奖励,记录0票还可以提供该用户之前是否在该帖子上投票的信息,即使他们后来撤回了赞成票或反对票。

作为最后一个考虑因素,您应该将您的投票更改操作包装在事务中,并对要UPDATE的行进行过度限定,以防止与用户的下一个操作发生冲突,因为。。。嗯,互联网。