sunspot solr how to search multiple models correctly? All examples online fail

久未见 提交于 2019-12-03 15:22:09

The method you've found for searching multiple models is correct. However, it appears that the meaning of your search is not what you intended. It looks as if you're trying to say:

Give me all Profile records with these country and state values, and whose Match record has this looking_for_education value

Your search, however, says:

Give me all records of type Profile or Match that have all of these country, state and looking_for_education values

Because neither Profile nor Match have all of these fields in their respective searchable blocks, no single record can match the conditions you specify.

If I'm correct about your intended behaviour above, then you need to include the profile's associated match information in the profile's searchable block, like so:

class Profile < ActiveRecord::Base
  has_one :match

  searchable do
    string(:country)
    string(:state)
    string(:city)
    string(:looking_for_education) { match.looking_for_education }
    integer(:age_from)             { match.age_from              }
    integer(:age_to)               { match.age_to                }
  end
end

Here, we've told Sunspot to index properties of the profile's match association as if they lived on the profile itself. In the respective blocks, we've told Sunspot how to populate these values when the profile is indexed.

This will allow you to write your search using only the Profile model:

def index
  @search = Sunspot.search Profile do
    with(:country, params[:country])
    with(:state,   params[:state])      
    with(:looking_for_education, params[:looking_for_education])
    with(:age).between(params[:age_from]..params[:age_to])
  end

  @profiles = @search.results
end

This search will return only Profile records, while still reflecting the properties of each profile's match association, because we stored them when the profile was indexed.

Note that this increases complexity when you index your models. If a Match record changes, its associated profile now needs to be reindexed to reflect those changes.

This is what i am doing when i have to search for multiple models

Sunspot.search [Model1, Model2] do
  ....
end

@moises-zaragoza answered correctly your question but you have more issues than you think with what you want to do.

The first error:

 Using a with statement like 
  with(:age).between(params[:age_from]..params[:age_to])
 undefined method `gsub' for nil:NilClass

Is most likely produced because params[:age_from] and/or params[:age_to] are nil. I can't assure it because you haven't shown the stacktrace. You can fix by filter only when they are present: with(:age).between(params[:age_from]..params[:age_to]) if params[:age_from].present? and params[:age_to].present?

The second error

Related to your views. I am assuming you are rendering a collection or object with one of the rails helper partial object helpers, without specifying the partial (again, without the code this is more of a good guess than anything else):

<%= render @results %>

or

<% @results.each do |result| %>
  <%= render result %>
<% end %>

When Rails does not have a partial specified, it guesses the partial name depending on the object type. In this case, if your object is for example of class Educator, which might be a subclass of Profile, Rails will look for the partial 'educators/_educator.html.erb. Make sure you render the proper partial depending on the object type and this will ensure you render what you want.

Here the answer for search different model on matching string using with

searchable(:auto_index => AppConfig.solr.auto_index) do
  string :category_name, :stored => true
  text :content, :stored => true
  text :title
  string :company_id, :stored => true
  time :published_on
end

search do |q|
  if params[:keyword].present?
    q.fulltext params[:keyword] do
      fields(:deal_data)
    end
  end
  if (ids = params["company_id"]).present?
    ids = ids.split(",")
    q.with(:company_id,ids) #here company id formate should be ["***","***"]
  end
end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!