I am using rails 4.0 with sunspot solr. I wish to do a this:
(read_flag IS TRUE) OR ( (read_flag IS NIL) AND (fulltext
params[:search] is true))
This is my code in (post.rb):
#search = Post.search do
any_of
with :model_id,params[:model_id]
all_of
with :model_id, nil
fulltext params[:search] do
fields(:title,:tags)
end
end
end
end
However, the code above will generate this error
undefined method 'fulltext' for #<Sunspot::DSL::Scope:0x007ff641ef2f38>
So I tried changing all_of to all. But it is not returning what I want.
The model file (post.rb) is indexed as per below
searchable do
integer :user_id
text :title, :boost => 2
integer :model_id
end
Can anyone advice on how should i structured my query? Couldn't find any relevant questions on stackoverflow.
I'm sure you have probably moved beyond this long ago, so for the benefit of anyone who might have found this question, I was struggling with a similar search using any_of and fulltext. I found ending the conjunction/disjunction before the fulltext seems to work:
#search = Post.search do
any_of
with :model_id,params[:model_id]
all_of
with :model_id, nil
end
end
fulltext params[:search] do
fields(:title,:tags)
end
end
Related
I' trying to figure out what would be the best way to do a multi table search with elastic.co.
In particular, I was wondering if I could add more indexes to this search method.
Chapter.rb
def self.search(params)
fields = [:title, :description, :content ]
**tables** = [Chapter.index_name, Book.index_name]
tire.search(**tables**, {load: true,page: params[:page], per_page: 5}) do
query do
boolean do
must { string params[:q], default_operator: "AND" } if params[:q].present?
end
end
highlight *fields, :options => { :tag => '<strong>' }
end
The above example works without the Tables. How to make it work with the tables ?
If you're adding more indexes then you are moving away from it being a model-centric search. That's probably fine as I guess you'll be handling the search results differently on account of them being from different indexes.
In which case I think you can do:
Tire.search([Chapter.index_name, Book.index_name],
page: params[:page],
... etc ...
) do
query do
... etc ...
end
end
It does mean that you won't be able to do stuff like load: true because you've moved outside of knowing what model to load the results for.
From digging around in the code (here) it looks like you might be able to specify multiple indexes even for a model-centric search. Something like:
tire.search({
index: [Chapter.index_name, Book.index_name],
load: true,
... etc ...
I haven't tried it though and I'm doubtful as to whether it will work - again because of not being able to load the results into a specific model once multiple indexes are involved.
I am trying to implement solr search into one of my rails project. My problem statement is to be able to search upon my models and show relevant results along with auto suggest. Could someone help me to complete it properly. At the moment I am trying to use sunspot solr although its not working for me as expected. I can see some indexing has been created in my project but the search is not working. Also there is no gem for auto suggest. Below are some snippets of my code. And yes I have gone through other links for solr and it did not solve my problem.
Category Model
class Category < ActiveRecord::Base
attr_accessible :name, :parent_category_id, :image, :image_file_name, :image_content_type, :image_file_size
has_and_belongs_to_many :events, :join_table => :categories_events
has_attached_file :image
searchable do
text :name
end
end
My Controller
if params.has_key?(:category)
puts "Inside Index Search"
puts params[:category]
#search = Category.ransack do
fulltext params[:category]
end
#category = #search.result.first
I am getting the results into #category and using it in my view to display.
Thanks in advance. I really appreciate your help. :-)
What does the method Category.ransack do ? I assume that you are using sunspot gem to integrate Solr into your project. If so use Category.search to search you index. Then use
#search.results
not
#search.result
So your code should look like this:
#search = Category.search do
fulltext params[:category]
end
#category = #search.results.first
You can also write it shorter:
#category = Category.search do
fulltext params[:category]
end.results.first
Remember that before you can use index in Solr, you have run:
rake sunspot:solr:reindex
If you are looking for information about implementing autocomplete on Solr, please read this article: http://olgagr.github.io/ruby/solr/how-to-implement-autocomplete-with-solr-and-ruby-on-rails
Some time ago I also struggled with this topic.
I solved it. There was a conflict between Solr and Ransack gem and that's why I could not get the resultset. It needed the below changes and its working now.
#search = Sunspot.search(Category) do
fulltext params[:search]
end
#category = #search.results
EDIT
My answer might not seem complete so just adding the code snippet that worked for me.
My Model
searchable do
text :name, :as => :name_textp
text :description, :as => :description_textp
text :category_strings, :as => :category_strings_textp
string :get_valid_dates, :multiple => true
integer :category_ids, :multiple => true
boolean :active
boolean :company_display
end
My Controller
search_results = Sunspot.search(Event) do
fulltext current_search
with(:category_ids, [ id ])
with(:active, true)
with(:company_display, true)
paginate(:page => #current_page, :per_page => page_size)
end
Hope it helps.
It conflicts of Solr & Ransack method search.
So please user solr_search instead of search
ex:
search = Product.solr_search do
fulltext 'random'
end
search.results
My trouble with this snippet is that it's returning an integer -1 which means a universal Message that is shared in other accounts as well.
def build_results
search = Sunspot.new_search(Message) do
any_of do
member.lists.map { |list| with :enterprise_list_id, list.search_id }
end
How can I add on to this statement to query all Message's with -1 as a search_id but scope it so that it belongs exclusively to member.account ?
I'm trying to scope it as so :
searchable :include => :repliable do
integer :account_id do
repliable.try(:account_id)
end
and..
def build_results
search = Sunspot.new_search(Message) do
with :account_id, member.account_id
But this returns nothing even though I know for a fact that there are search results that should be returned because they share a commont account_id.
If I understood your question correctly then you just need to add this statements in your Message searchable block.
searchable do
integer :some_search_ids, :multiple => true do
member.lists.map { |list| list.search_id} if member.present?
end
integer :member_account_id do
member.account_id if member.present?
end
end
then,
def build_results
search = Sunspot.new_search(Message) do
with(:some_search_ids, some_list_search_id)
with(:member_account_id, some_member_account_id)
end
end
Now I'm using a gem called 'mailboxer' for messaging system.https://github.com/ging/mailboxer
I'd like to implement 'keyword search function' for inbox, sentbox, and trash.
If I don't care about search keyword, it is fetching the result without any problem by coding like this
inbox... #messages = current_user.mailbox.inbox.page(params[:page]).per(10)
sentbox... #messages = current_user.mailbox.sentbox.page(params[:page]).per(10)
trash... #messages = current_user.mailbox.trash.page(params[:page]).per(10)
But I sometimes want to filter the result with search keyword.
Assume search keyword was 'test' this time, the result should be only the records that contain 'test' within body attribute in notifications table.
How can I do this for each above such as inbox, sentbox, and trash??
I tried this but it didn't work at all :(
#messages = current_user.mailbox.inbox.search_messages(#search).page(params[:page]).per(10)
#messages = current_user.mailbox.sentbox.search_messages(#search).page(params[:page]).per(10)
#messages = current_user.mailbox.trash.search_messages(#search).page(params[:page]).per(10)
The solution is to monkey patch both the Mailboxer::Receipt and Mailboxer::Models::Messageable module to enable searching by box type:
class Mailboxer::Receipt < ActiveRecord::Base
...
if Mailboxer.search_enabled
searchable do
text :subject, :boost => 5 do
message.subject if message
end
text :body do
message.body if message
end
integer :receiver_id
# Add mailbox_type to sunspot search field
string :mailbox_type
boolean :trashed
boolean :deleted
end
end
end
and under the Messageable module, I've added new search__messages method for each mailbox type:
module Mailboxer
module Models
module Messageable
def search_messages(query)
# Replaces 'search' with alias 'solr_search' since ransack search clashes with solr search method
#search = Mailboxer::Receipt.solr_search do
fulltext query
with :receiver_id, self.id
end
#search.results.map { |r| r.conversation }.uniq
end
# Adds additional Mailboxer search functionality to search by box type
def search_inbox_messages(query)
#search = Mailboxer::Receipt.solr_search do
fulltext query
with :receiver_id, self.id
with(:mailbox_type).equal_to("inbox")
end
#search.results.map { |r| r.conversation }.uniq
end
def search_sent_messages(query)
#search = Mailboxer::Receipt.solr_search do
fulltext query
with :receiver_id, self.id
with(:mailbox_type).equal_to("sentbox")
end
#search.results.map { |r| r.conversation }.uniq
end
def search_trash_messages(query)
#search = Mailboxer::Receipt.solr_search do
fulltext query
with :receiver_id, self.id
with :trashed, true
with :deleted, false
end
#search.results.map { |r| r.conversation }.uniq
end
end
end
end
With this, in your controller you can simply use the newly defined methods to do the box type searching.
current_user.search_inbox_messages(query[:keywords])
current_user.search_sentbox_messages(query[:keywords])
current_user.search_trash_messages(query[:keywords])
IMPORTANT NOTE: Make sure to regenerate the Solr indexes after adding the new search fields, otherwise nothing will show up:
bundle exec rake sunspot:solr:reindex
Hope this helps!
I have a project model in my rails 3.1 application and I want to use Solr to run a search on it.
I defined the search like this:
searchable do
text :nr, :boost => 5 # nr is integer
text :name, :boost => 5
text :description, :boost => 2
text :client do
client.name
end
text :tasks do
tasks.map(&:name)
end
end
The project-nr, in my model just called nr, type integer, is the most used reference for finding a project.
Now besides having a search form I still want my projects ordered by the nr when no search was performed, but this does not work - my project seem to be in totally random order.
The code of my ProjectsController index action looks like this:
def index
#search = Project.search do
fulltext params[:search]
paginate :page => params[:page]
order_by :nr, :desc
end
#projects = #search.results
##projects = Project.active.visible.design.order("nr desc")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #projects }
end
But when I visit then myapp/projects I get a
Sunspot::UnrecognizedFieldError in ProjectsController#index
No field configured for Project with name 'nr'
error...
any ideas what I need to do to order by nr. ?
thanks
Okay, I solved it by turning the nr field to an integer in my searchable:
searchable do
integer :nr
text :name, :boost => 5
text :description, :boost => 2
text :client do
client.name
end
text :tasks do
tasks.map(&:name)
end
end
Now I was able to order it nicely but I couldn't perform a text search on the project_nr anymore.
So I added a virtual attribute name_number to my Project model and instead searched on this field.
def name_number
"#{self.nr} - #{self.name[0..24]}"
end
Now I have ordering and searching in place... If there are other / better ideas, keep em coming!