Rails: запрос с внутренним соединением, сортировка по ассоциации и отсутствие повторяющихся записей - PullRequest
0 голосов
/ 06 мая 2020

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

Подводя итог:

Встреча проводится между двумя пользователями, один из которых - booker, а другой - bookee. Встреча также has_many :time_options, которую пользователь может предложить, а затем, когда bookee выбирает и подтверждает одну из предложенных time_options, start_time применяется к аналогичному атрибуту start_time встреч. Модели структурированы следующим образом:

#appointment.rb
belongs_to :booker, foreign_key: :booker_id, 
                                class_name: 'Profile'
belongs_to :bookee, foreign_key: :bookee_id, 
                                class_name: 'Profile'
has_many :time_options, dependent: :destroy

scope :order_by_start_time, -> {
               joins(:time_options)
               .order("COALESCE(appointments.start_time, time_options.start_time) DESC")
              }

def self.search(search)
  if search
    search_term = "%#{search}%"
    joins(
          "INNER JOIN profiles ON profiles.id IN (appointments.booker_id, 
                                                  appointments.bookee_id)"
         )
    .where(
           "CONCAT_WS(' ', profiles.first_name, profiles.last_name) ILIKE :term 
            OR appointments.service_title ILIKE :term", 
            term: search_term
           )
  else
    where(nil)
  end
end
#time_option.rb 
 belongs_to :appointment, touch: true
 belongs_to :profile

#profile.rb
 belongs_to :user, touch: true
 has_many :booker_appointments, foreign_key: :booker_id,
                                class_name: 'Appointment', 
                                dependent: :nullify
 has_many :bookee_appointments, foreign_key: :bookee_id, 
                                class_name: 'Appointment', 
                                dependent: :nullify

Я пытаюсь разрешить пользователям искать встречи по номеру service_title или имени другого пользователя (независимо от того, booker или bookee). Затем я хочу упорядочить эти результаты поиска по start_time. Либо start_time самой встречи (которая устанавливается только при подтверждении встречи), либо, если встреча еще не подтверждена, и это start_time равно nil, вместо этого используйте самое раннее start_time связанных time_options.

Итак, в контроллере я делаю что-то вроде:

  def index
    @appointments = Appointment.all_profile_appointments(@profile)
    if params[:search]
      @upcoming_appointments = @appointments.search(params[:search])                             
                                            .order_by_start_time
                                            .page(params[:page])
                                            .per(12)
    else
      @upcoming_appointments = @appointments.order_by_start_time
                                            .page(params[:page])
                                            .per(12)
      end
    end

Однако мой метод поиска возвращает дубликаты, я полагаю, из-за INNER JOIN. И если я добавлю .distinct до или после order_by_start_time method, я получу замечательную ошибку: PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list

Так что я почти уверен, что мне просто нужно написать более сложный и точный оператор SQL ; но, между необходимостью присоединения к таблице profiles для поиска по имени, необходимостью присоединения / объединения таблицы time_options для упорядочивания по start_time, я не совсем уверен, где делать go дальше. В качестве фона я использую postgresql и Rails 4.

TL; DR: я пытаюсь найти записи о встречах по имени профиля, который забронировал или был забронирован для встречи. Затем я хочу заказать этот запрос по appointments.start_time или, если время начала встречи не подтверждено, то по самому раннему time_options.start_time, связанному с встречей. И я пытаюсь обойтись без кучи повторяющихся записей.

...