Reputation: 956
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!
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'
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!
Upvotes: 4
Views: 2465
Reputation: 3792
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
Upvotes: 3