我想为不同的促销活动向用户表示感谢。例如,在写文章时,给文章打分……
我正在寻找一个灵活的解决方案,其中我可以调整不同的行动和总分也变化的分数。
如果我将这些点保存在一个表中,以后就不能再更改它们了。如下所示:
$request->user()->points += 10;
$request->user()->save();
当我每次重新计算分数时,性能如何?如下所示:
$articlepoints = $user->articles->count();
&votepoints = $user->votes->count();
$totalpoints = $articlepoints*10+$votepoints*5;
还有没有别的选择?
发布于 2018-10-10 03:02:12
如果您试图最小化每个负载上的计数操作,则可以使用Cache::remember()方法。你只需要决定你想要多长时间“过期”这个cccced值。我假设你将在用户模型中运行这个函数,但是你可以在任何你想要的地方运行它:
$articlepoints = Cache::remember('articlepoints_'.$this->id, 5, function () {
return $this->articles->count();
});
这段代码的作用是检查缓存中"articlepoints_userID“索引下是否存在该用户的文章指针。userID是动态的,将为每个用户存储不同的值。如果该索引存在,则将其用作值。
如果索引还不存在于缓存中,您可以将其传递到函数中,在函数中返回计算出的值并将其存储5分钟。您可以对等式中的每个值(投票点和累计点)执行此操作,并使用您想要的任何过期时间。
使用这段代码,可以极大地减少对count()函数的调用。但是,根据缓存驱动程序的不同,您可能仍然需要对其中的每一个进行数据库调用或磁盘调用。为了避免这种类型的开销,您需要研究不同的缓存驱动程序,例如redis。
查看Laravel Cache docs,看看您可以使用缓存做的所有其他很酷的事情。学习缓存系统是提高Laravel应用程序性能的好方法。
发布于 2018-10-10 03:25:19
这类事情的一种常见模式是保留一个表,以记录导致积分的每个事件,并在用户表或某种包含每个用户的记录的统计数据表上的列中聚合总积分。这使您能够保留每个事件的记录,如果您更改了每个事件类型的价值,则可以追溯地重新计算总计,并且可以访问总计(并在查询中使用它们),而不必每次都计算它们。
当我做这类事情时,我使用数据库中的触发器在存储事件时自动更新聚合总数,以便应用程序逻辑保持整洁。下面是一个适用于MySQL的示例:
CREATE TABLE `users` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`total_activity_points` int(11) UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `users_username_uk` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `users` (`username`) VALUES ('Bob');
INSERT INTO `users` (`username`) VALUES ('Alice');
CREATE TABLE `activities` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`title` varchar(20) NOT NULL,
`points` int(11) UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `activities_title_uk` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `activities` (`title`,`points`) VALUES ('Article', 10);
INSERT INTO `activities` (`title`,`points`) VALUES ('Vote', 5);
CREATE TABLE `user_activities` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(11) UNSIGNED NOT NULL,
`activity_id` int(11) UNSIGNED NOT NULL,
`create_date` DATETIME NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `user_activities_fk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `user_activities_fk_2` FOREIGN KEY (`activity_id`) REFERENCES `activities` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DELIMITER //
DROP TRIGGER IF EXISTS `after_insert_user_activities` //
CREATE TRIGGER `after_insert_user_activities`
AFTER INSERT
ON `user_activities`
FOR EACH ROW
BEGIN
DECLARE v_total INTEGER DEFAULT 0;
SET v_total = (SELECT SUM(`activities`.`points`)
FROM `user_activities`
INNER JOIN `activities` ON `activities`.`id`=`user_activities`.`activity_id`
WHERE `user_activities`.`user_id` = NEW.`user_id`);
UPDATE `users`
SET `total_activity_points` = v_total
WHERE `users`.`id` = NEW.`user_id`;
END;
//
DELIMITER ;
DELIMITER //
DROP TRIGGER IF EXISTS `after_delete_user_activities` //
CREATE TRIGGER `after_delete_user_activities`
AFTER DELETE
ON `user_activities`
FOR EACH ROW
BEGIN
DECLARE v_total INTEGER DEFAULT 0;
SET v_total = (SELECT SUM(`activities`.`points`)
FROM `user_activities`
INNER JOIN `activities` ON `activities`.`id`=`user_activities`.`activity_id`
WHERE `user_activities`.`user_id` = OLD.`user_id`);
UPDATE `users`
SET `total_activity_points` = v_total
WHERE `users`.`id` = OLD.`user_id`;
END;
//
DELIMITER ;
INSERT INTO `user_activities` (`user_id`,`activity_id`,`create_date`) VALUES (1,1,NOW());
INSERT INTO `user_activities` (`user_id`,`activity_id`,`create_date`) VALUES (1,2,NOW());
INSERT INTO `user_activities` (`user_id`,`activity_id`,`create_date`) VALUES (2,2,NOW());
INSERT INTO `user_activities` (`user_id`,`activity_id`,`create_date`) VALUES (2,2,NOW());
DELIMITER //
DROP TRIGGER IF EXISTS `after_update_activities` //
CREATE TRIGGER `after_update_activities` AFTER UPDATE ON `activities`
FOR EACH ROW
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_userId INT(11) UNSIGNED;
DECLARE v_total INT(11) UNSIGNED;
DECLARE user_id_cursor CURSOR FOR SELECT DISTINCT(`user_activities`.`user_id`) FROM `user_activities` WHERE `user_activities`.`activity_id`=NEW.`id`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;
IF NEW.`points` != OLD.`points` THEN
OPEN user_id_cursor;
get_user_ids: LOOP
FETCH user_id_cursor INTO v_userId;
IF v_finished = 1 THEN
LEAVE get_user_ids;
END IF;
-- recalculate and store scores
SET v_total = (SELECT SUM(`activities`.`points`)
FROM `user_activities`
INNER JOIN `activities` ON `activities`.`id`=`user_activities`.`activity_id`
WHERE `user_activities`.`user_id` = v_userId);
UPDATE `users`
SET `total_activity_points` = v_total
WHERE `users`.`id` = v_userId;
END LOOP get_user_ids;
CLOSE user_id_cursor;
END IF;
END;
//
DELIMITER ;
DELIMITER //
DROP TRIGGER IF EXISTS `before_delete_activities` //
CREATE TRIGGER `before_delete_activities` BEFORE DELETE ON `activities`
FOR EACH ROW
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_userId INT(11) UNSIGNED;
DECLARE v_total INT(11) UNSIGNED;
DECLARE user_id_cursor CURSOR FOR SELECT DISTINCT(`user_activities`.`user_id`) FROM `user_activities` WHERE `user_activities`.`activity_id`=OLD.`id`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;
OPEN user_id_cursor;
get_user_ids: LOOP
FETCH user_id_cursor INTO v_userId;
IF v_finished = 1 THEN
LEAVE get_user_ids;
END IF;
-- recalculate and store scores
SET v_total = (SELECT SUM(`activities`.`points`)
FROM `user_activities`
INNER JOIN `activities` ON `activities`.`id`=`user_activities`.`activity_id`
WHERE `user_activities`.`user_id` = v_userId
AND `user_activities`.`activity_id` != OLD.`id`);
UPDATE `users`
SET `total_activity_points` = v_total
WHERE `users`.`id` = v_userId;
END LOOP get_user_ids;
CLOSE user_id_cursor;
END;
//
DELIMITER ;
当点值发生更改或活动被删除时,activities表中的触发器会更新总计。before delete触发器是必需的,因为MySQL不对级联删除运行delete触发器。
https://stackoverflow.com/questions/52724923
复制相似问题