Home > Blockchain >  Optimizing database query in Rails 5
Optimizing database query in Rails 5

Time:05-11

I have 4 models

module Vehicle
  has_many :routes
end

module Route
  has_many :route_users
  belongs_to :vehicle
end

module RouteUser
  belongs_to :route
  belongs_to :user
end

module User
  belongs_to :route_user
end

My goal is to return the most recent driver (a user) through the aggregate.rb; to be specific, I need user id, first_name, last_name.

 
  attributes = {
    id: vehicle.id,
    ... other attributes ...
  }

  attributes.merge!(
    driver: {
      id: vehicle.routes.last.route_users.last.user.id,
      first_name: vehicle.routes.last.route_users.last.user.first_name,
      last_name: vehicle.routes.last.route_users.last.user.last_name
    }
  ) if vehicle.routes.present? && vehicle.routes.last.route_users.present?
 

As you can see, .merge! loads a bunch of information and dramatically slows down the aggregate.rb return. Is there any way to optimize this return to make it faster? Am I missing something?

CodePudding user response:

You can improve your User model to make the query easier.

class User < ApplicationRecord
  has_many :route_users
  has_many :routes, through: :route_users
  has_many :vehicles, through: :routes
end

And when the query is big from one side, the best way is two invert the logic, and make a query from user, example:

First fetch last_user_drive, and after that, use his fields to merge into attributes

last_user_driver = User.joins(routes: :vehicle).where(vehicle: {id: vehicle.id}).order('routes.created_at').last

...
attributes.merge!(
  driver: {
    id: last_user_driver.id,
    first_name: last_user_driver.first_name,
    last_name: last_user_driver.last_name
  }
) if last_user_driver.present?
  • Related