Using Rails 3.2, Ruby 1.9, will_paginate. I have 100,000 records, and tested the following queries:
# 1000+ms to load
#shops = Shop.where(:shop_type => #type).paginate(:include => :photos, :page => params[:page], :per_page => 25, :order => 'created_at DESC')
# 1000+ms to load
#shops = Shop.paginate(:include => :photos, :page => params[:page], :per_page => 25, :order => 'created_at DESC')
# 1000+ms to load
#shops = Shop.order('created_at DESC').limit(25)
# 1+ms to load
#shops = Shop.paginate(:include => :photos, :page => params[:page], :per_page => 25)
I noticed that the order option is incredibly slow. Test results show that will_paginate is not a problem.
How should I change it so that the query with order can be sped up.
Yes, try to create index on the order column. It will speed it up.
Related
Riding on the previous question:
Ruby on rails - pagination on search result
This is my model:
def self.search(title, company, location_id)
if location_id.present?
paginate :conditions => ['title LIKE ? AND company LIKE ? AND location_id = ?', "%#{title}%", "%#{company}%", location_id].last(200),
:page => #page,
:per_page => 20,
:order => "total DESC"
else
paginate :conditions => ['title LIKE ? AND company LIKE ?', "%#{title}%", "%#{company}%"].last(200),
:page => #page,
:per_page => 20,
:order => "total DESC"
end
end
When I click to page 2, the url shows:
.../search?company=&location_id=&page=2&title=&utf8=%E2%9C%93
and the page show page 1 result..
What's wrong?
I think the problem is in this place: :page => #page . Where is the variable #page from ? You probably should send this variable when you call the search method of Post class
In the model:
def self.search(title, company, location_id, page)
if location_id.present?
paginate :conditions => ['title LIKE ? AND company LIKE ? AND location_id = ?', "%#{title}%", "%#{company}%", location_id].last(200),
:page => page,
:per_page => 20,
:order => "total DESC"
else
paginate :conditions => ['title LIKE ? AND company LIKE ?', "%#{title}%", "%#{company}%"].last(200),
:page => page,
:per_page => 20,
:order => "total DESC"
end
end
In the controller:
def search
...
page = params[:page]
#posts = Post.search(title, company, location_id, page);
end
In the model:
def self.search(title, company, location_id, page) ... :page => page, ... end
In the controller:
def search ... page = params[:page]; #posts = Post.search(title, company, location_id, page); end
I'm building a site for users to post events they wish to sell tickets for.
I'm writing a query where the conditions are the follow:
active equals true
sales_stop is < Time.now
The problem I am having is coming up with a condition which tests whether or not a record's sales_stop time is less than Time.now.
Below is what I have as of now:
#events = Event.paginate :page => params[:page],
:conditions => {:active => true},
:order => "created_at DESC"
In turn, I've been toying around with the sales_stop condition with no luck.
I've been trying something like this:
#events = Event.paginate :page => params[:page],
:conditions => {:active => true, :sales_stop < Time.now},
:order => "created_at DESC"
This of course doesn't work.
Does anyone know how I can set this query up so that I only retrieve records where the sales_stop attribute is less than Time.now?
Thank you.
Use the alternate syntax for :conditions, which uses a bind-style:
#events = Event.paginate :page => params[:page],
:conditions => ['active = ? AND sales_stop < ?', true, Time.now],
:order => "created_at DESC"
This should work:
#events = Event.paginate :page => params[:page],
:conditions => ['active=? AND sales_stop < ?', true, Time.now],
:order => "created_at DESC"
Just a different syntax.
How to paginate posts with will_paginate, so that first page shows 10 latest posts in ASC order.
Thanks!
If I understood correctly, this code should do the job in your controller.
def index
#posts = Post.paginate :page => params[:page], :per_page => 10, :order => 'created_at ASC'
end
Try adding this to your post model right at the top:
cattr_reader :per_page
##per_page = 10
default_scope :order => 'created_at DESC'
How do you effectively search among many fields in a model?
# user.rb model
def self.search(search, page)
paginate :per_page => 20, :page => page,
:conditions =>
['name like ? OR notes like ? OR code like ? OR city like ? OR state like ?,
"%#{search}%","%#{search}%","%#{search}%","%#{search}%","%#{search}%"
], :order => 'name'
This code is horrible for any more than a few fields, and it doesn't return a result if, for instance word #1 comes from :name and word #2 comes from :code. Is there a more elegant way?
I think that do work
def self.search(search, page)
fields = [:name, :notes, :code, :city, :state]
paginate :per_page => 20, :page => page,
:conditions => [fields.map{|f| "#{f} like ?"}.join(' OR '),
*fields.map{|f| "%#{search}%"}], :order => 'name'
You can use searchlogic
def self.search(search, page)
search_cond = resource.search(name_or_notes_or_code_or_city_or_state_like => search.to_s)
search_cond.all
end
Hope you got the idea
def self.search(search, page)
fields = %w(name notes code city state)
paginate :per_page => 20, :page => page,
:conditions => [fields.map{|f| "#{f} like :phrase"}.join(' OR '), {:phrase => search}],
:order => 'name'
I'm encountering a problem with will_paginate while doing a complex find.
: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. MySQL's IN usually does "or" searches, but I need "and". 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. But if it has to paginated, the SQL that is generated is similar to:
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.
Is there a better way to do this search that might work with 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):
#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}"