简体   繁体   中英

Search multiple models with Tire and ElasticSearch

I have two models, Posts and Channels that I'm searching using Tire and ElasticSearch.

Currently, everything works just fine. However, I'm performing two searches and returning the results of both. I'd like to consolidate this into one – and search both models at the same time.

Below is the controller action I'm using to do just this:

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

Below is the Post model:

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

Below is the Channel model:

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

Then, in my view, I have two loops:

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

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

Again – my goal is to execute one search, and display the results of posts and channels jumbled together using one loop.

Any help would be greatly appreciated... I'm pulling my hair out with this one!


UPDATE

Adding app trace...

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'

ANSWER

I replaced my browse action in the controller with:

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

And then looped through @results in the view – and it worked!

You can use,

      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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM