我正在尝试从数据库中随机选择一条记录并将其显示在我的视图中。问题是我不希望重复所选的随机记录,直到所有记录至少被选中一次。例如,让我们说我的表有10条记录,所以我想选择任意一条随机记录,并确保在选择其他9条记录至少一次之前,不再选择该随机选择的记录。
片段:
offset = rand(Quote.count)
@qotd = Rails.cache.fetch( "term", :expires_in => 6.seconds){ Quote.offset(offset).first }
答案 0 :(得分:2)
如果你需要跟踪用法,那么你需要的是某种序列列,用随机值填充它,并在你使用它们时将它们取出来。当它们全部为NULL时,使用随机值重新种子并重新执行。
答案 1 :(得分:0)
您需要一个单独的位置来存储已在当前流程之外显示的记录。该过程可能会死亡,或者您将运行多个进程(如果它是用于生产目的,那肯定是这种情况)。
与tadman proposed相反,我不建议将序列存储在数据库中,因为这会使添加新记录变得更复杂。
相反,我会添加一个简单的displayed
(布尔)列(或单独的表)和rely on what has been proposed in a different thread,但会根据您的特定用例进行调整。所以查询可能是这样的:
@qotd = Quote.where(displayed: false).order("RAND()").limit(1)
当然是
@qotd.update_attribute :displayed, true
稍后。
如果找不到候选人,则必须重置所有记录的displayed
列。所有这些,(查询,更新和重置)应该可能在一个方法中发生。
答案 2 :(得分:0)
我的建议是添加一个类似" display_count"到你的桌子。当您想要显示随机项时,您只需发出如下查询:
quote = Quote.where(
display_count: Quote.select("MIN(display_count)")
).order("RANDOM()")
quote.update_attribute(:display_count, quote.display_count + 1)
这样你总是选择一个显示最少的项目,并在检索它后递增它。这应该(几乎)保证每次运行此代码时,都会得到一个新项目。