我想每天将我的用户与他/她社区中的不同用户进行匹配。目前,我使用这样的代码:
@matched_user = User.near(@user).order("RANDOM()").first
但我希望每天都有一个不同的@matched_user。我无法在 Stack 或 API 中找到任何让我了解如何做到这一点的东西。我觉得它应该比使用 cron 执行 rake 任务更简单。(我在 postgres 上。)
我想每天将我的用户与他/她社区中的不同用户进行匹配。目前,我使用这样的代码:
@matched_user = User.near(@user).order("RANDOM()").first
但我希望每天都有一个不同的@matched_user。我无法在 Stack 或 API 中找到任何让我了解如何做到这一点的东西。我觉得它应该比使用 cron 执行 rake 任务更简单。(我在 postgres 上。)
每当我发现自己渴望共享“内存”或瞬态状态时,我都会对自己说“这就是(分布式)缓存的发明目的”。
@matched_user = Rails.cache.fetch(@user.cache_key + '/daily_match', expires_in: 1.day) {
User.near(@user).order("RANDOM()").first
}
注意:虽然为缓存条目指定 TTL 会告诉 Rails/缓存系统尝试在给定的时间范围内保持该值,但不能保证它会。特别是,积极尝试回收内存的缓存可能会在其所需expires_in
时间之前使条目过期。
对于这个特定的用例,这应该没什么大不了的,但是在业务/域逻辑需要定期生成持久值的情况下,您确实必须将其考虑到您的数据库中。
使用 PostgreSQL 的SETSEED
功能怎么样?我用日期播种,这样种子每天都会改变,但一天之内,种子会保持一致。:
User.connection.execute "SELECT SETSEED(#{Date.today.strftime("%y%d%m").to_i/1000000.0})"
@matched_user = User.near(@user).order("RANDOM()").first
您可能希望在使用后播种一个随机值,以便将来对 random 的任何调用都不会有偏差:
random = User.connection.execute("SELECT RANDOM()").to_a.first["random"]
# Same code as above:
User.connection.execute "SELECT SETSEED(#{Date.today.strftime("%y%d%m").to_i/1000000.0})"
@matched_user = User.near(@user).order("RANDOM()").first
# Use random value before seed to make new seed:
User.connection.execute "SELECT SETSEED(#{random})"
为了便于阅读,我将这些步骤分成了不同的部分。您可以稍后优化查询。
1)查找到今天早上的所有用户记录。这样计数就会冻结。
usrs_till_today_morning = User.where("created_at <?", DateTime.now.in_time_zone(Time.zone).beginning_of_day)
2)提取所有ID
user_ids = usr_till_today_morning.pluck(:id)
3)今天日期将是一个范围(1..30),但将在一天中保持不变。
day_today = Time.now.day
4)当天选择同一个ID
todays_user_id = user_ids[day_today % user_ids.count]
@matched_user = User.find(todays_user_id)
所以它会通过全天保持相同的记录来给你随机的用户记录!!