user3675188
user3675188

Reputation: 7419

How to reduce number of queries in this case on Rails

I need to do a bunch of queries.

In this case I think I query a result by many times,

Not completed in one query.

How to make my search results can be done by one query ?

  q = WeatherLog.nearby(100, longitude, latitude)
  if start_time and end_time
    @weather_logs = q.where(datetime: start_time..end_time)
  elsif start_time
    @weather_logs =  q.where("datetime > ?", start_time)
  elsif end_time
    @weather_logs =  q.where("datetime < ?", end_time)
  end
    @weather_logs = @weather_logs.order(datetime: :asc).first(2000)

Upvotes: 0

Views: 121

Answers (1)

Pete
Pete

Reputation: 2246

The first thing to realize is that ActiveRecord does not execute a query until it aboultely has to (lazy loading). While there are a number of lines of code building up the query, the query is only executed on methods like .all, .each, .first etc. So from a performance standpoint your code is ok as your only executing one query to the database and not many.

However you can tweak the code to make it more human readable and maintainable:

class WeatherLog < ActiveRecord::Base
   # ...
   class << self
     def between_times(times)
       after_time(times[:start_time]).before_time(times[:end_time])
     end

     def after_time(time)
       return self.all if time.nil?
       where('datetime > ?', time)
     end

     def before_time(time)
       return self.all if time.nil?
       where('datetime < ?', time)
     end
   end
end

Using self.all effectively skips the query condition while still enabling query chaining. This makes it possible to remove of all the if/else logic. Then you can chain the queries (or create a helper method within WeatherLog):

WeatherLog.nearby(100, longitude, latitude).between_times(start_time: start_time, end_time: end_time)

Upvotes: 1

Related Questions