многотабличный поиск с несколькими фильтрами в postgresql - rails

Просмотрев несколько вариантов, включая pg_search, я не могу найти ресурс, который может помочь мне понять, как организовать поиск по нескольким таблицам и с несколькими фильтрами. У меня есть две модели, профиль и тема, обе связаны через unique_id. Я бы хотел, чтобы пользователь выбирал из множества фильтров по многим моделям и возвращал результаты. Например, я хочу, чтобы пользователь мог искать атрибут name в модели профиля и атрибут grade в предметной модели и возвращать список, соответствующий эти параметры поиска. У меня нет проблем с созданием одного поискового фильтра, но когда я добавляю дополнительные фильтры для разных категорий, кажется, что другие поисковые фильтры не взаимодействуют друг с другом. Ниже приведен некоторый мой код. Рад добавить больше кода, просто не знаю, где с этим быть. Мы будем очень признательны за любую помощь или направление, которое вы могли бы предоставить.

БД профилей

class CreateProfiles < ActiveRecord::Migration
  def change
    create_table :profiles do |t|
      t.integer :unique_id
      t.string :name
      t.integer :age
      t.string :sex
      t.references :user, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end

Тематическая БД

class CreateSubjects < ActiveRecord::Migration
  def change
    create_table :subjects do |t|
      t.integer :unique_id
      t.string :subject
      t.integer :grade
      t.references :user, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end

Модель профиля

class Profile < ActiveRecord::Base

include PgSearch

  belongs_to :user

    def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
    attributes = row.to_hash
    Profile.create! attributes
   end 
  end


end

Тематическая модель

class Subject < ActiveRecord::Base

      include PgSearch

      belongs_to :user

      def self.import(file)
        CSV.foreach(file.path, headers: true) do |row|
        attributes = row.to_hash
        Subject.create! attributes
       end 
      end

    end

person richiepop2    schedule 02.08.2016    source источник


Ответы (1)


Взгляните на запросы таблиц соединения Rails и цепочка методов Rails для начала.

Давайте посмотрим на некоторые примеры того, что вы можете сделать. Допустим, вы хотите найти пользователей с именем профиля «Джон» и предметом с оценкой 100. Вы можете сделать следующее:

@users = User.where(profiles: { name: "John" }, subjects: { grade: 100 }).joins(:profiles, :subjects)

Обратите внимание, что использование метода хеширования работает, только если вы фильтруете на основе определенных значений. Допустим, теперь вы хотите найти пользователей, чье имя профиля содержит слово «Джон» (например, «Джон», «Джон Смит» или «Джон Доу») и оценка выше 85, вы должны сделать следующее:

@users = User.where("profiles.name ILIKE ? AND subjects.grade > ?", "John%", 85).joins(:profiles, :subjects)

Насколько я помню, запрос ILIKE работает с Postgres, а не с MySQL. Обратите внимание на тот факт, что в обоих утверждениях вы должны указать в запросе имя соединяемой таблицы, а также вызвать метод joins.

Итак, теперь, когда вы знаете, как объединять таблицы, мы можем теперь посмотреть, как использовать параметры и области для фильтрации.

class User
  scope :by_profile_name, -> (input) do
    where("profiles.name = ?", input[:profile_name]).joins(:profiles) if input[:profile_name]
  end

  scope :by_subject_grade, -> (input) do
    where("subjects.grade = ?", input[:subject_grade].to_i).joins(:subjects) if input[:subject_grade]
  end
end

Тогда в вашем контроллере у вас будет:

@users = User.by_subject_grade(params).by_profile_name(params)

Это только грубое начало, взгляните на ссылки выше для более подробной информации.

person Greg Answer    schedule 02.08.2016
comment
большое спасибо, Грег. Это помогло мне начать. - person richiepop2; 03.08.2016