How do i go about searching in Ruby on Rails? - ruby-on-rails

I would like to implement a simple search. Let's say the user enters 'york', then I would like to find all records that has a matching substring like 'new york' or 'yorkshire'.
So far I have figured out I will have to use the find method, but I can't figure out how to match for substrings.

city = params[:q]
User.find(:all, :conditions=>["city like :text", {:text=>"%#{city}%"} ] )

You might want to take a look at the Thinking Sphinx plugin for doing such full text search . Solr is also another option .

Related

Postgres LIKE in a rails application

I have a Postgres LIKE statement like this:
#favorites.find_each do |profiles|
#related_profiles = Profile.where('name LIKE ?', '%' + profiles.name + '%')
end
What I'm trying to do is loop through the favourites variable and find all profiles that contain some characters of the name.
For example a name "jasson jackson" should be found if the name contains "jackson" or "jasson"
The query you're looking for would be like:
Profile.where("name LIKE ?", "%#{profiles.name}%")
But note that your #related_profiles may not be properly assigned as the result would be the same as saying:
Profile.where("name LIKE ?", "%#{#favorites.last.name}%")
whereas, I doubt if that is what you need.
Also note that the it would be an ActiveRecord::Collection, an array like object.
A way to work around that is to initialize #related_profiles = [] and then at each point through your loop, you could do:
#related_profiles +=
Profile.where("name LIKE ?", "%#{profiles.name}%")
or another way is:
names = #favorites.map(&:name)
query = names.map{|name| "name LIKE '%#{name}%'"}.join(" OR ")
OR
query = #favorites.map{|favorite| "name LIKE '%#{favorite.name}%'" }.join(" OR ")
THEN
profiles = Profile.where(query)
UPDATE
Based on a comment from #joshrumbut, I decided to reimplement using the bind parameters.
However, code clarity is a bit lost, but here's a way it could be done:
names = #favorites.map(&:name)
query = names.map{|favorite| "name LIKE ?" }.join(" OR ")
profiles = Profile.where(query, *names.map{|name| ("%#{name}%")})
Based on the comment from #muistooshort, I removed the quotes from the first two queries and I think this approach looks a bit cleaner, as he suggested. From the docs
Profile.where('name like any(array[?])', names.map { |s| "%#{s}%" })
For better results with this type of search, You can try use FTS (Full text search).
Rails has a gem with this feature implemented:
https://github.com/Casecommons/pg_search
PgSearch builds named scopes that take advantage of PostgreSQL's full text search.
With this gem installed on your project, just use this statement for search:
PgSearch.multisearch("jasson")
Other option is Elasticsearch, with him you can index yours registers for a better text search.
Hope it helps :)
I'll try with Postgres patterns and "OR" operator - postgres doc
names = #favorites.map(&:name)
Profile.where('name LIKE %(?)%', names.join('|'))

Boost exact match searchkick / elastic search Rails 4

Having trouble getting exact matches to display first. I am using searchkick with elastic search on my rails 4 app.
For example, if a user searches "coke" .. "coke zero" will display first. I would like it the other way around.
If there is documentation on this can you please point me in that way? I am having an overly hard time finding a solution.
I have tried boosting the title field ('specific' in my case):
fields: ["specific^20"]
and boosting where the field matches the query exactly (although I don't know if i'm implementing this correctly):
boost_where: [:specific == :q]
Nothing seems to be working. Thank you!
Try this .....
Model.search "hi#example.com", fields: [{column_name1: :exact}, :column_name2]
Hope this will help you.
I had a similar issue. I solved it like this.
Model.search(
'search term',
fields: [
{'name^2' => :phrase},
{'name' => :word_start},
]
)

How can I match a partial string to a database's object's attribute? Regexp?

I have a database containing a list of movies. A typical entry look like this:
id: 1,
title: "Manhatten and the Murderer",
year: 1928,
synopsis: 'some text...'
rating: 67,
genre_id, etc. etc.
Now I'm trying to make a series of search tests pass and so far I have made a single test case pass where if you type the title "Manhatten and the Murderer" in a text field it will find the movie that you want. The problem is with partial matching.
Now I'd like a way to search "Manhat" and match the record "Manhatten and the Murderer". I also want it to match with any movie that has "Manhat" in it. For example, it would return maybe 2 or 3 others like title: "My life in Manhattan", title: "The Big Apple in Manhattan" etc. etc.
Below is the code that I have so far in my Movie model:
def self.search(query)
# Replace this with the appropriate ActiveRecord calls...
if query =~ where(title:)
#where(title: query)
binding.pry
end
end
My question is, how can I set this up? My problem is the "where(title:) line. One thought was to use Regexp to match the title attribute. Any help would be appreciated! Thanks.
Use a query that searches a substring in between:
name = "Manhattan"
Movie.where("title like ?", "%#{name}%")
For example:
%Manhattan will get you: Love in Manhattan
Manhattan% will get: Manhattan and Company
%Manhattan% will get you both: [Love in Manhattan, Manhattan and Company]
But, if you're searching through movies synopsis, you should use Thinking Sphinx or Elastic Search
For example, with Elastic Search, you could set the synopsis like this:
Add app/indices/movie_index.rb:
ThinkingSphinx::Index.define :movie, :with => :active_record do
# fields
indexes title, :sortable => true
indexes synopsis
end
Index your data with rake ts:index
And then run Sphynx with: rake ts:start
You can search just like this:
Movie.search :conditions => {:synopsis => "Manhattan"}
Elastic Search is a great alternative to ThinkingSphinx, there's even a RailsCast about it, so you should definitely take a look to see what really suites you best... Hope this helps!
You do not need regex to find movies that have the search string. You can use SQL query like this:
Movie.where('title LIKE ?','Batman%')
That would return all movies start with "Batman"
Movie.where('title LIKE ?','%Batman%')
That would return all movies that have Batman anywhere in it's title.
I think you figured out the '%' is a joker character in the query.
One option is to run a search server alongside your Rails application. It is certainly my go to solution. This route offers a ton of features not found within Rails itself and might be overkill, but worth consideration.
I use Sphinx and implement it using the thinking-sphinx gem.
Resources:
http://pat.github.io/thinking-sphinx/
http://sphinxsearch.com/

Difficult search in ruby on rails

How can I search first in model (i know how to do this). And then search in this array for more concretence? As you see:
#articles = Article.find(:all, :conditions => { :ART_ID => #search.map(&:ARL_ART_ID)})
#a = #articles.find_all{|item| item.ART_ARTICLE_NR == search.upcase }
First i search in model, but thanks to my db) it have many wrong results, so i must to clarify my array. But there how to search like sql:
like % %
Now it search very strong: if i search AC451, it's good, but if AC45 or C451 it's nothing fetches. How to say him so that before and after
search
could be everything?
Like this, maybe?
item.ART_ARTICLE_NR.include?(search.upcase)
You are asking for trouble by not following rails naming conventions an using upper case column names. That said, the rails3 way to do it is probably:
#articles = Article.where(:ART_ID => #search.map(&:ARL_ART_ID)).where('ART_ARTICLE_NR LIKE', "%#{search.upcase}%")
Without knowing what #search is, it's hard to be sure. But you should read up on the active record guide on the rails 3 query format.
It's maybe not straigtforward answer, but have you considered using ransack gem?

How to build sort urls on Rails?

I am working on the index page of a listing controller, which needs several sort options. Query string is needed to determine the sort option that is active for the current page. I have used a workaround for this problem by hardcoding the query string into the sort links:
=link_to "Lowest Price","/listings?sort_by=price&order=asc", :class=>"#{'active' if request.query_string =~ /sort_by=price&order=asc/ }"
But there are two problems with this. First, this is too fragile. Second, it doesn't support a search query nor any other parameters -- otherwise it breaks.
What I need is a way to change the sort options without assuming that the query string will stay intact...
Not sure if there is a best practice for doing this. I'm taking the long road and just adding helpers to parse url to hash, hash to url, and I still don't know what to do about the active link problem. It could be a while to do all that.
Any suggestions would be appreciated.
You can do this by providing key/value pairs to any URL helper. For example:
listings_url(:sort_by => "asc", :order => "asc")

Resources