获取随机记录优先记录尚未选择的记录

时间:2014-11-02 18:04:03

标签: ruby-on-rails activerecord

我试图找到一种方法来获取一些随机记录而不重复,至少在我从表中获取所有记录一次之前。

我有一些问题(3000)。

我创建一个测验选择一些随机问题(30)。我需要用所有问题创建测验,所以不用重复,直到我使用所有3000个问题。然后我可以开始向我们提出另一个循环的问题。

在单个用户环境中,我可以添加一个字段" count"每次我使用问题时都会在我的问题表中增加,但我有一个多用户环境,所以我不能污染问题表。

有什么想法吗?

4 个答案:

答案 0 :(得分:3)

您必须创建一个中间表。

假设您的模型为UserQuestion

rails g migration create_users_questions user_id:integer question_id:integer
rake db:migrate

这将在您的数据库中生成users_questions表。

然后,在user.rb

has_and_belongs_to_many :questions

和您的question.rb

has_and_belongs_to_many :users

新表格的每一行都包含user_idquestion_id

因此,要为用户@user提供未使用的问题:

通用语法

@unused_questions = Question.where('id not in (?)',@user.questions.map(&:id))


Rails~> 4.0语法 [感谢D-Side]

@unused_questions = Question.where.not(id:@user.question_ids)

并向@user添加一个新的,用过的问题(让@question说出来)

@user.questions<<@question

那是故事的结尾......

最后,要重置@用户问题的状态:

if @unused_questions.empty?       # we have defined that above
    @user.questions.clear
end

然后再次添加......

答案 1 :(得分:0)

如果您不想添加任何数据库字段,最好的方法是使用redis

1-在redis中添加所有问题ID

$redis.sadd 'set_one', Question.pluck(:id)

2-点击选择随机id的方法并将其从列表中删除

def get_rand_question
 random_id =  $redis.spop "set_one"
 Question.find random_id
end

答案 2 :(得分:0)

我认为您可以使用缓存来存储已排序的未使用问题的商店ID。

available_question_ids = Rails.cache.read('available_question_ids')
if available_questions_ids.nil? || available_question_ids.empty?
  available_question_ids = Question.pluck(:id).to_a.shuffle
end
quiz_questions_ids = available_question_ids.pop(30)
Rails.cache.write('available_question_ids', available_question_ids)

现在,您可以使用quiz_questions = Question.find(quiz_questions_ids)找到您的问题。

答案 3 :(得分:0)

您需要添加其他模型来跟踪用户与特定问题的互动。

用户问题:

  • belongs_to:user
  • belongs_to:问题
  • used(boolean)

用户:

  • has_many:user_questions
  • has_many:问题,通过:: user_questions

然后,您将需要运行有限的随机查询:

user_question = User.user_questions.where(used:false).order(“RANDOM()”)。first

这将为您提供下一个要使用的问题。一旦它被回答,你会将它标记为已使用,因此它不会被再次拾取。

重新生成测验时,您需要重置为false。或者你可以使用计数......但是如果你的上一次测验没有使用所有问题,你需要以某种方式重置,否则你的计数将被取消。