Rails 3中,will_paginate,随机,重复的记录,Postgres的,过setSeed

2019-06-24 01:31发布

我的电影与属性的数据库。 我想一个查询批次按随机顺序这些电影的回归模板与分页。 我使用will_paginate。 我试过如下:

## MoviesController

movies = Movie.get_movies(query_string)   # a method in Movie model that takes in 
                                          # a query_string and fetches movies 
                                          # with user-set params

@movies = movies.order('random()').page(params[:page]).per_page(16)

这工作得很好,除了电影是从页重复页面。 解决这个问题已经张贴在这里和这里 。 这些链接解释说,因为随机()种子是从页面到页面复位,没有一致性和OFFSET变得毫无用处。 他们提供的MySQL用户带来了极大的解决方案,其兰特(n)函数需要一个种子ñ。 Postgres的,但是,不做到这一点。 你必须发出随机的()在之前, 为了申报SELECT 过setSeed(N)。

所以,我想Postgres的方式来设置种子:

@movies = movies.select('setseed(.5)').order('random()').page(params[:page]).per_page(16)

奇怪的是,这回电影对象,绝对没有属性。 下面是从模板中提出:

::加载ActiveModel在MissingAttributeError电影#行动

缺少的属性:some_movie_attribute

我调试此,一旦堆达到action_controller /金属,@movies包含:

[#<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >]

Movie对象的那个数字(18)对应于从查询返回的电影的数量。

我还尝试了以下以查看是否的setSeed(N)为通过去除随机顺序方法的问题:

@movies = movies.select('setseed(.5)').page(params[:page]).per_page(16)

这回同非属性如上奠定了影片对象。 所以看来过setSeed(n)是确实的问题。

我尝试了几个解决的,如:

# MoviesController

movies = Movie.get_movies(query_string)
shuf_movs = movies.shuffle  ## effectively turns shuf_movs into an array

@movies = shuf_movs.paginate(:page => params[:page], :per_page => 16)

这也返回了重复电影的网页。 我以为这是因为分页需要的对象的东西进行排序,你可以不设置在阵列#洗牌种子。 于是,我就写,将临时存储的ID通过在电影对象,责令我自己的随机编码。 (请原谅马虎的代码):

# Movie model

attr_accessor :rand_id

# MoviesController

movies = get_movies(query_string)
movies_count = movies.count
r = Random.new
nums = []
rand_movs = []
id = 1
while nums.count != movies_count
  num = r.rand(0..movies_count - 1)
  if !(nums.include?(num))
    movie = movies[num]
    movie.rand_id = id
    rand_movs << movie
    nums      << num
    id += 1
  end
end

@movies = rand_movs.sort_by { |a| a.rand_id }.paginate(:page => params[:page], :per_page => 16)

这仍然产生了不同的页面重复的电影。 此时我意识到will_paginate不会在你面前被分类PAGINATE所谓服用。 所以我尝试这样做:

@movies = rand_movs.paginate(:order => 'rand_id', :page => params[:page], :per_page => 16)

这仍然重复记录。 :订单- >“rand_id”,是因为忽略当你处理ActiveRecord的对象,而不是为了数组仅事项。

所以过setSeed(N)似乎是我实现使用will_paginate随机不重复的记录,唯一的希望。 有任何想法吗?

谢谢!

Answer 1:

没有一个Postgres人,但是......我会尝试

Movie.connection.execute "select setseed(0.5)"
Movie.where(...).order('random()').page(params[:page]).per_page(15)

至于Array#shuffle没有服用一粒种子,它使用Kernel.rand所以你可以使用它的种子Kernel.srand



Answer 2:

尝试通过字段的数组来select

@movies = movies.select(['setseed(.5)', 'some_movie_attribute']).order('random()').page(params[:page]).per_page(16)

有些结果使用some_movie_attribute ,这是不被查询中选择,所以不可用。 将其作为选择的领域之一应该可以解决这一个。



文章来源: Rails 3, will_paginate, random, repeating records, Postgres, setseed failure