Поиск нескольких моделей с помощью Tire и ElasticSearch

У меня есть две модели: сообщения и каналы, которые я ищу с помощью Tire и ElasticSearch.

В настоящее время все работает просто отлично. Однако я выполняю два поиска и возвращаю результаты обоих. Я хотел бы объединить это в одно — и искать обе модели одновременно.

Ниже приведено действие контроллера, которое я использую для этого:

def browse
    @user = current_user
    @channels = Channel.search(params)
    @posts = Post.search(params)
end

Ниже представлена ​​модель Post:

class Post < ActiveRecord::Base
  attr_accessible :description, :name, :tag_list, :thumbnail_image, :status, :post_type, :subtitle, :summary, :visibility, :user
  acts_as_taggable

  has_one :publication
  has_one :user, :through => :publication
  has_many :subscriptions, dependent: :destroy


  has_many :channel_post_connections, dependent: :destroy
  has_many :channels, :through => :channel_post_connections

  accepts_nested_attributes_for :channel_post_connections
  accepts_nested_attributes_for :channels
  accepts_nested_attributes_for :publication
  accepts_nested_attributes_for :user


  has_many :post_pages, dependent: :destroy

  validates_presence_of :post_type, :name, :subtitle, :tag_list, :summary, :thumbnail_image, :if => :post_is_published?


  include Tire::Model::Search
  include Tire::Model::Callbacks
  index_name 'posts_index'

  def self.search(params)
    tire.search(load: true) do
      query { string params[:query], default_operator: "AND" } if params[:query].present? 
      sort { by :created_at, "desc" } if params[:query].blank?
    end
  end

  def to_indexed_json
    to_json(methods: [:user_first_name, :user_display_name])
  end

  def user_first_name
    self.user.first_name if self.user.present?
  end

  def user_display_name
    self.user.display_name if self.user.present?
  end

end

Ниже приведена модель канала:

class Channel < ActiveRecord::Base
    attr_accessible :title, :description, :cover_image, :status, :writable, :visibility, :thumbnail_image

    has_one :channel_publication
    has_one :user, :through => :channel_publication

    has_many :channel_subscriptions

    has_many :channel_post_connections

    accepts_nested_attributes_for :channel_publication
    accepts_nested_attributes_for :user

    mount_uploader :thumbnail_image, ChannelThumbnailImageUploader

    include Tire::Model::Search
    include Tire::Model::Callbacks
    index_name 'channels_index'

    def self.search(params)
        tire.search(load: true) do
            query { string params[:query], default_operator: "AND" } if params[:query].present? 
          sort { by :created_at, "desc" } if params[:query].blank?
        end
    end

    def to_indexed_json
      to_json(methods: [:user_first_name, :user_display_name])
    end

    def user_first_name
      self.user.first_name if self.user.present?
    end

    def user_display_name
      self.user.display_name if self.user.present?
    end

end

Тогда, на мой взгляд, у меня есть две петли:

- @posts.each do |post|
  %h3
    = post.name

- @channels.each do |channel|
  %h3 
    = channel.title

Опять же, моя цель — выполнить один поиск и отобразить результаты сообщений и каналов, смешанных вместе, используя один цикл.

Любая помощь будет принята с благодарностью ... Я рву на себе волосы с этим!


ОБНОВИТЬ

Добавление трассировки приложения...

app/controllers/posts_controller.rb:111:in `[]'
app/controllers/posts_controller.rb:111:in `block in browse'
app/controllers/posts_controller.rb:110:in `browse'

ОТВЕЧАТЬ

Я заменил действие просмотра в контроллере на:

def browse
    @user = current_user
    @search_items = Tire.search(['posts_index', 'channels_index'],{load: true}) do |search|
      if params[:query].present? 
        search.query do |q|
          q.string params[:query], default_operator: "AND"
        end
      end
      search.sort { by :created_at, "desc" }
    end
    @results = @search_items.results
end

А затем просмотрел @results в представлении — и это сработало!


person cmw    schedule 23.09.2013    source источник


Ответы (1)


Ты можешь использовать,

      def browse
        @search_items = Tire.search(['posts_index', 'channels_index'],{load: true}) do |search|
          search.query do |q|
            q.string params[:query], default_operator: "AND" if params[:query].present? 
          end
          search.sort { by :created_at, "desc" } if params[:query].blank?
        end
        @results = @search_items.results
      end
person Vamsi Krishna    schedule 23.09.2013
comment
Я попытался поместить это в блок def self.search(params) - безуспешно: неопределенный метод `each' для #‹Tire::Search::Search:0x007f92ba26e270›. Как вы рекомендуете мне реализовать это, учитывая приведенный выше код? Я пытался перепрофилировать это несколькими способами, и не добился никакого успеха. Однако это определенно похоже на то, что я ищу. - person cmw; 23.09.2013
comment
Вам нужно поместить его в метод просмотра, а не в метод self.search. Проверьте мой отредактированный ответ. - person Vamsi Krishna; 24.09.2013
comment
Ах, хорошо, спасибо - я думаю, что теперь я довольно близок ... однако после реализации вашего отредактированного ответа я получаю TypeError: не могу преобразовать символ в целое число - person cmw; 24.09.2013
comment
Вы держите пари - спасибо, что нашли время, чтобы помочь мне. Я добавил трассировку приложения в свой исходный пост. Строка 111 — это запрос {... - person cmw; 24.09.2013
comment
Попробуйте получить хеш params перед вызовом Tire.search, или вы можете альтернативно использовать блочный метод. Пожалуйста, смотрите мое редактирование для блочного подхода. Проверьте эти ссылки github.com/karmi/tire/issues/197 и github.com/karmi/tire/issues/840 - person Vamsi Krishna; 24.09.2013
comment
Это сработало! Пришлось вынести метод sort из search.query — и все заработало. Благодаря тонну! - person cmw; 24.09.2013
comment
Да, извините за это. Рад, что ты это понял. Отредактировал мой ответ. - person Vamsi Krishna; 25.09.2013