简体   繁体   English

Rails:将will_paginate与复杂的关联一起使用find

[英]Rails: Using will_paginate with a complex association find

I'm encountering a problem with will_paginate while doing a complex find. 我在进行复杂的查找时遇到了will_paginate的问题。

:photo  has_many   :tags,   :through => :tagships
:item   has_many   :photos
:photo  belongs_to :item


@photos = @item.photos.paginate :page => params[:page],
                                :per_page => 200,
                                :conditions => [ 'tags.id IN (?)', tag_ids],
                                :order => 'created_at DESC',
                                :joins => :tags,
                                :group => "photos.id HAVING COUNT(DISTINCT tags.id) = #{tag_count}"

I want to fetch all the photos who have all the tags in the tag_ids array. 我想获取所有在tag_ids数组中具有所有标签的照片。 MySQL's IN usually does "or" searches, but I need "and". MySQL的IN通常会执行“或”搜索,但我需要“和”。 I found how to modify IN to mimic "and" behavior here and it works fine when using model.find(), also works as long as the number of records fetched is lower than my :per_page count. 我发现如何在此处修改IN以模仿“和”行为并且在使用model.find()时效果很好,只要获取的记录数小于我的:per_page计数,它也可以工作。 But if it has to paginated, the SQL that is generated is similar to: 但是,如果必须分页,则生成的SQL类似于:

SELECT count(*) AS count_all, photos.id HAVING COUNT(DISTINCT tags.id) = 1 AS photos_id_having_count_distinct_tags_id_1 FROM `photos`(...)

which doesn't work. 这不起作用。 Other have seen this bug and were able to move their count() out of the query, but I don't think that's possible in my case. 其他人已经看到了该错误,并能够将其count()移出查询,但是对于我而言,这是不可能的。

Is there a better way to do this search that might work with will_paginate? 有没有更好的方法来进行可能与will_paginate一起使用的搜索? If its the only way to do this, I guess I should look into another pagination plugin? 如果这是唯一的方法,我想我应该看看另一个分页插件吗?

Thanks! 谢谢!

FYI, here's what I finally found to fix this: 仅供参考,这是我终于找到的解决方法:

@photos = WillPaginate::Collection.create(current_page, per_page) do |pager|
    result = @item.photos.find :all, :conditions => [ 'tags.id IN (?)', tag_ids] ,:order => 'created_at DESC', :joins => :tags, :group => "photos.id HAVING COUNT(DISTINCT tags.id) = #{@tags.count}", :limit => pager.per_page, :offset => pager.offset
    pager.replace(result)

    unless pager.total_entries
      pager.total_entries = @item.photos.find(:all, :conditions => [ 'tags.id IN (?)', tag_ids] ,:order => 'created_at DESC', :joins => :tags, :group => "photos.id HAVING COUNT(DISTINCT tags.id) = #{@tags.count}").count
    end
  end

You have to manually construct the paginated set using the page number as an offset and using the tags to make a join query. 您必须使用页码作为偏移量并使用标签进行联接查询来手动构造分页集。 Kinda clunky. 有点笨拙。

My first stab at this (sorry don't have time to test it right now... will update if I do) would be something like the following (added the :select and changed the :group): 我的第一个选项(对不起,现在没有时间进行测试...如果我这样做,将会更新)将类似于以下内容(添加了:select并更改了:group):

@photos = @item.photos.paginate :page => params[:page],
                                :per_page => 200,
                                :select => "photos.*, COUNT(DISTINCT tags.id) AS tag_count",
                                :conditions => [ 'tags.id IN (?)', tag_ids ],
                                :order => 'created_at DESC',
                                :joins => :tags,
                                :group => "photos.id HAVING tag_count = #{tag_count}"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM