Поиск отношения без второго запроса

#ruby-on-rails #performance #ruby-on-rails-3

#ruby-on-rails #Производительность #ruby-on-rails-3

Вопрос:

Мой вопрос заключается в том, как выполнять различные уровни поиска в базе данных, ограничивая при этом количество запросов.

Давайте начнем с простого:

 @companies = Company.where("active = ?", true)
  

Допустим, мы выводим записи из этого набора. Затем нам нужно:

 @clientcompanies = @companies.where("client_id = ?", @client.id)
  

Мы показываем что-то из @clientcompanies. Затем мы хотим детализировать дальше.

 @searchcompanies = @clientcompanies.where("name LIKE ? OR notes LIKE ?", "#{params[:search]}%", "#{params[:search]}%")
  

Являются ли эти три утверждения наиболее эффективным способом добиться этого?

Если действительно база данных каждый раз запускается со всей таблицы Company, есть ли способ ограничить область действия, чтобы каждое из приведенных выше утверждений занимало меньшее количество времени по мере уменьшения размера набора?

На случай, если это имеет значение, я использую Rails 3 как на MySQL, так и на PostgreSQL.

Ответ №1:

Это не становится намного более оптимизированным, чем то, что вы уже делаете. Ровно ноль из этих инструкций выполнят SQL-запрос, пока вы не попытаетесь выполнить итерацию по результатам. Вызов таких методов, как all , first , inspect any? , each , и т.д., будет осуществляться при выполнении запроса.

Каждый раз, когда вы подключаете новый where или другой метод arel, он добавляется к sql-запросу, который он выполнит в конце. Если где-то посередине вы хотите увидеть запрос, который будет выполнен, вы можете сделать puts @searchcompanies.to_sql

Обратите внимание, что если вы выполняете эти команды в консоли, каждая инструкция, похоже, выполняет SQL-запрос только потому, что консоль автоматически выполняется .inspect в введенной вами строке.

Надеюсь, я ответил на ваш вопрос 🙂

Здесь есть отличный railscast:http://railscasts.com/episodes/239-activerecord-relation-walkthrough это объясняет, как работает ActiveRelation, и что вы можете с этим сделать.

Редактировать:

Возможно, я неправильно понял ваш вопрос. Вы указали, что после каждого where вызова вы отображали информацию из запроса. Каков вариант использования для этого? Вы отображаете все компании на той же странице, на которой вы отфильтровали компании из поиска? Если вы отобразите что-то из этого самого первого запроса, то вы будете извлекать каждую отдельную строку company из своей базы данных (что не будет очень масштабируемым или производительным при большем количестве записей о компаниях).

Не имело бы смысла отображать информацию только из @searchcompanies переменной?

Комментарии:

1. Мой вариант использования для отображения данных из этих различных уровней запросов прост — представьте страницу, которая «детализирует» некоторые данные и показывает пользователю подробную информацию о каждом уровне. Допустим, я хочу показать пользователю некоторый образец companies , затем некоторую выборку clientcompanies вместе с фактическим поиском пользователя. Мой вопрос зависит от этого случая, когда мне нужно выполнить эти запросы, но я хочу выполнять их как можно проще.