How do I do an "or" based search in sunspot? - ruby-on-rails

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.

Related

Exact Term Search In Rails

I'm trying to build a basic search where only the entire exact search term shows results. Currently it is showing results based on individual words.
Here's the code from the model:
def search
find(:all, :conditions => ['term' == "%#{search}%"])
end
Sorry in advance. I'm very new to rails!
Thank you.
Remove the % from "%#{search}%" so it's "#{search}".
% is a wildcard that matches every result containing the word. So "%tea%" for example would match tear, nestea, and steam, when that's not what you want.
This should yield an exact match:
def search
find(:all, :conditions => ['term' == "#{search}"])
end
Your code doesn't work for several reasons.
You do not pass any value to that method. Therefore search will always be nil.
The ['term' == "%#{search}%"] condition doesn't make much sense because - as I said before - search is undefined and therefore the condition will is the same as ['term' == "%%"]. The string term is not equal to %% therefore the whole condition is basically: [false].
Rails 5.0 uses a different syntax for queries. The syntax you used is very old and doesn't work anymore.
I would do something like this:
# in your model
scope :search, -> (q) {
q.present? ? where("column_name LIKE :query", query: "%#{q}%") :none
}
# in your controller
def set_index
#b = Best.search(params[:search]).order(:cached_weighted_score => :desc)
end

How to filter results by their associations when using PG search gem?

I am using PG search gem in my Rails app. Say I get a set of articles in my controller:
#articles = Article.search(params[:search]).with_pg_search_highlight
the problem with PG search here is that I get back an array, instead of AR object. So now I cannot do something like
#research_articles = #articles.where(category: 'research')
Because I will get a
undefined method `where' for Array
Now I can make several queries from that one action, but what would be a better solution to this problem?
pg_search gem provides pg_search_scope.
See the doc https://github.com/Casecommons/pg_search#pg_search_scope
You can also chain where condition with pg_search_scope.
What about changing the chain?
#articles = Article.where(category: 'research').search(params[:search]).with_pg_search_highlight
EDIT:
A way without making 2 queries would be:
#found_articles = Article.search(params[:search]).with_pg_search_highlight
#research_articles = #found_articles.select { |article| article.category == "research" }
You probably should define a scope (or even simple getter would be enough here) and reuse it:
def simple_search
pure = Article.search(params[:search])
(block_given? ? yield(pure) : pure).with_pg_search_highlight
end
And then:
#articles = simple_search
#research_articles = simple_search { |ss| ss.where(category: 'research') }

Daisy chaining conditions in Rails controller action.

The index method of my controller looks as follows:
def index
if params["feed_source_id"]
#feeds = Feed.find_all_by_feed_source_id(params["feed_source_id"])
else
#feeds = Feed.all
end
I just added the Metasearch Gem to my app, and it defines the search in my index as:
#search = Feed.search(params[:search])
How can I daisy chain both of these conditions so that #search will perform the search as well as include the find_all_by_feed_source_id condition?
Not sure what you're aiming at - besides doing both searches in the index action? Do you want a union or intersection of both search results?
If you want a union, you could do something like
#feeds = #feeds | #search.all
in addition to all the code above, which would give you a terrible performance.
I had a brief look at the Metasearch Gem, and it should give you the possibility to include the feed_source_id as one of the parameters.
You want the AND of these conditions, right?
I think this should work:
Feed.search({ :feed_source_id_eq => params[:feed_source_id] }.merge(params[:search]))

Rails - how to search based on a boolean field? (MySQL error)

I'm running the following query
#projects = #company.projects.where("active = ?", true).order("created_at ASC")
and I'm getting the error:
`ActiveRecord::StatementInvalid: Mysql::ParseError: You have an error in your SQL...`
the error points to the = '1'.
I've tried many variations on my query but I cannot figure out the problem. How can I solve this?
Try:
#projects = #company.projects.where(:active => true)
(it also works with strings 'active').
You can also look at
http://guides.rubyonrails.org/active_record_querying.html#hash-conditions
for more details.
There is also a nice railscast about this which explains why you might have problems (I'm not allowed to post 2 links so you should search for it :) )
You don't need to use parameterized queries with literals, just do this:
#projects = #company.projects.where("active = 1").order("created_at ASC")

Rails - Conditional Query, with ActiveRecord?

Given a query like:
current_user.conversations.where("params[:projectid] = ?", projectid).limit(10).find(:all)
params[:projectid] is being sent from jQuery ajax. Sometimes that is an integer and the above works fine. But if the use selects "All Projects, that's a value of '' which rails turns into 0. which yields an invalid query
How with rails do you say search params[:projectid] = ? if defined?
Thanks
I think you may have mistyped the query a bit. "params[:projectid] = ?" shouldn't be a valid query condition under any circumstances.
In any case, you could do some sort of conditional statement:
if params[:project_id].blank?
#conversations = current_user.conversations.limit(10)
else
#conversations = current_user.conversations.where("project_id = ?", params[:project_id]).limit(10)
end
Although, I'd probably prefer something like this:
#conversations = current_user.conversations.limit(10)
#converstaions.where("project_id = ?", params[:project_id]) unless params[:project_id].blank?
Sidenotes:
You don't have to use .find(:all). Rails will automatically execute the query when the resultset is required (such as when you do #conversations.each).
Wherever possible, try to adhere to Rails' snakecasing naming scheme (eg. project_id as opposed to projectid). You'll save yourself and collaborators a lot of headaches in the long run.
Thanks but if the where query has lets say 3 params, project_id, project_status, ... for example, then the unless idea won't work. I'm shocked that Rails doesn't have a better way to handle conditional query params
EDIT: If you have multiple params that could be a part of the query, consider the fact that where takes a hash as its argument. With that, you can easily build a parameter hash dynamically, and pass it to where. Something like this, maybe:
conditions = [:project_id, :project_status, :something_else].inject({}) do |hsh, field|
hsh[field] = params[field] unless params[field].blank?
hsh
end
#conversations = current_user.conversations.where(conditions).limit(10)
In the above case, you'd loop over all fields in the array, and add each one of them to the resulting hash unless it's blank. Then, you pass the hash to the where function, and everything's fine and dandy.
I didn't understand why you put:
where("params[:projectid] = ?", projectid)
if you receive params[:project] from the ajax request, the query string shouldn't be:
where("projectid = ?", params[:projectid])
intead?
And if you are receiving an empty string ('') as the parameter you can always test for:
unless params[:projectid].blank?
I don't think i undestood your question, but i hope this helps.

Resources