Sunspot Rails - get matched substring in fulltext search - ruby-on-rails

i need your help. I want to get the matched string in a full text sunspot search.
Thats how my code looks like at the moment
search2 = WebsiteEntry.search do
fulltext params[:q]
end
search2.each_hit_with_result do |hit, res|
#match = <Here I need your Help, i need the substring on which sunspot made a hit>
#results.push SearchResult.new(res, hit.score, #match)
end
end
Now, if i´m searching for the word "test" sunspot looks for everything where "test" is a substring and case insensitive.
For example: Sunspot return the matched words "FirstTest" or "TEST2" or "testit".
Is it possible to get the matched string?. I need the string on which sunspot hitted
From "FirstTest" in need the hit "Test". Because i would like to display where sunspot founded a match. So, from "FirstTest" i need the substring "Test". From "TEST2" i need "TEST" and so on.
Thank you.

i have now the solution for my problem. The "hit" - Objekt in the "each_hit_with_result" function return a list with the matched substrings, called "highlight"
search2 = WebsiteEntry.search do
fulltext params[:q] do
highlight :domain
end
end
search2.each_hit_with_result do |hit, res|
hit.highlight(:domain).format { |word| puts "highlight: "+word}
No I´m getting each matched string form the full text search. The Problem was, that i didn`t mark my attribute as highlight. Thx

Related

How to make search box case-insensitive in rails?

I have simple search form in Rails, but when I using the search box, I need to enter the name exactly.
For instance, when I try to search for "more" it doesn't return anything, but when I do with "More", then it returns the records, So it seems like it behaves in a case-sensitive way.
Is it possible to make this case-sensitive way?
Here is my code
def self.search(search)
if search
star = Star.find_by(who: search)
if star
self.where(star_id: star)
else
Post.all
end
else
Post.all
end
end
You could do something like:
star = Star.where("UPPER(who) = ?", search.upcase).take
or
star = Star.where("LOWER(who) = ?", search.downcase).take
Either way, this coerces both your search term as well as the who value in the database before comparing them, which should get you the results that you need

Multiple word search in one field

I have search functionality with this code in the 'search.rb' file:
votsphonebooks = votsphonebooks.where("address like ?", "%#{address}%") if address.present?
There are multiple fields, this is just one of them.
How can I successfully change this line into something like a map to include multiple words.
Eg. If they type in '123 Fake St' - it will look for exactly that, but I want it to search for '123', 'Fake', 'St'.
First thing you should do is split the address by spaces:
addresses = params[:address].split(" ")
Then what you need is a OR query, you could do it by using ARel.
t = VotsPhoneBook.arel_table # The class name is my guess
arel_query = addresses.reduce(nil) do |q, address|
q.nil? ? t[:address].matches("%#{address}%") : q.or(t[:address].matches("%#{address}%"))
end
results = Post.where(arel_query)
Try using REGEXP instead of LIKE:
address_arr = address.split(" ")
votsphonebooks = votsphonebooks.where('address REGEXP ?',address_arr.join('|')) unless address_arr.blank?

Rails 4 search separate keywords with wrong number of bind variables (1 for 2)

I have this tentative search function, however, it is limited to search one chunk of keyword only.
def self.search(search)
search_condition = "%" + search + "%"
active.where("lower(title) LIKE ?", search_condition.downcase)
end
E.g. I have this title: "Peter Paul Mary"
If I search "peter Mary", it doesn't show.
I found this code useful in this post:
def self.search(search)
if search
search_length = search.split.length
find(:all, :conditions => [(['name LIKE ?'] * search_length).join(' AND ')] + search.split.map { |name| "%#{name}%" })
else
find(:all)
end
end
Unfortunately, it's in older rails.
So, how do I translate this into rails 4?
Update:
I've changed to something like this:
def self.search(str)
search = str.split.map{|w| "(lower(title) LIKE ? )"}.join(" OR ")
values = str.split.map{|w| "%#{w.downcase}%"}.map(&:inspect).join(', ')
.where("#{search}", values)
end
But it raises this error:
ActiveRecord::PreparedStatementInvalid (wrong number of bind variables (1 for 2) in: (lower(title) LIKE ? ) OR (lower(title) LIKE ? )):
Please advise.
If you happen to be using Postgres with your app, then you can easily take advantage of PG's Full Text Search capabilities using the pg_search gem.
You can also plug into frameworks like Solr or ElasticSearch to give you this functionality, but they will increase you development effort.
PG and MySQL both also have pattern matching functions that would allow you to search based on a regex string from the search values.

How do I do an "or" based search in sunspot?

I have several categories of facets I'm looking for and in one I want, when the user clicks more than one filter in that particular category, to have the results sunspot returns include everything that matches either of the choices, not only both. I tried this:
#search = ProfileSearch.new(search_params) do
facet_restriction = with(:grad_year,params[:grad_year])
facet(:grad_year, :exclude => facet_restriction)
end
But that doesn't seem to be working at all? Am I not using multiselect facets in the appropriate way or should I be looking at doing something entirely different?
Any thoughts would be appreciated.
I think it should be
#search = ProfileSearch.search(search_params) do
facet_restriction = with(:grad_year,params[:grad_year])
facet(:grad_year, :exclude => facet_restriction)
end
I do something like this:
grad_year_exclusions = []
if params[:grad_year].present?
grad_year_exclusions << with(:grad_year).any_of(params[:grad_year])
end
grad_year_exclusions.compact!
grad_year_exclusions = nil if grad_year_exclusions.empty?
facet(:grad_year, exclude: grad_year_exclusions)
(params[:grad_year] being an array)
Hope this helps.

Case insensitive and inclusive ActiveRecord queries?

I have views that print out a table of guides that have the word 'farming' in their titles.
def farming
t = Guide.arel_table
#guides = Guide.where(t[:title].matches('%farming'))
end
The problem is I want to show all guides that have at least any kind of spelling of the word 'farming' in it. So "Farming for Dummies" should show up in the search, too.
How do I do this?
In order to match Farming for Dummies you need to use farming%, i.e. % should be after the word farming.
Try the following to return all records with title including the word farming anywhere in title:
def farming
t = Guide.arel_table
#guides = Guide.where(t[:title].matches('%farming%'))
end

Resources