How would one correctly search multiple models in SunSpot Solr?
如何在SunSpot Solr中正确搜索多个模型?
Profile model
档案模型
has_one :match
searchable do
string :country
string :state
string :city
end
Match model
匹配模型
belongs_to :profile
searchable do
string :looking_for_education
integer :age_from
integer :age_to
end
ProfilesController#Index
ProfilesController#指数
def index
@search = Sunspot.search Profile, Match do
with(:country, params[:country])
with(:state, params[:state])
with(:looking_for_education, params[:looking_for_education]) <= from the 2nd model
end
@profiles = @search.results
end
This fails with:
这失败了:
Using a with statement like
with(:age).between(params[:age_from]..params[:age_to])
undefined method `gsub' for nil:NilClass
Removing the
with(:age).between(params[:age_from]..params[:age_to]) line then it tries to
删除with(:age).between(params [:age_from] .. params [:age_to])行然后尝试
then it tries to load the
然后它试图加载
view app/views/educators/educator.html.haml
which does not exist ( im only using
哪个不存在(我只使用
/app/views/profiles/_profile.html.haml
to show profiles
显示个人资料
EDIT #1:
What are good opensource projects in ruby on rails that use sunspot and solr in a bit more advanced way to have a look at? Maybe I can find the answer there. Any answer in this direction will also be accepted the bounty if it yields in resulting this issue, thx!
什么是使用太阳黑子和solr的红宝石轨道上的优秀开源项目,以更先进的方式来看看?也许我可以在那里找到答案。如果这个问题导致了这个问题,那么这个方向的任何答案也将被接受。
4 个解决方案
#1
7
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 thesecountry
andstate
values, and whoseMatch
record has thislooking_for_education
value向我提供包含这些国家/地区和州值的所有个人资料记录,其匹配记录具有此looking_for_education值
Your search, however, says:
但是,您的搜索说:
Give me all records of type
Profile
orMatch
that have all of thesecountry
,state
andlooking_for_education
values给我所有类型为Profile或Match的记录,其中包含所有这些country,state和looking_for_education值
Because neither Profile
nor Match
have all of these fields in their respective searchable
blocks, no single record can match the conditions you specify.
由于Profile和Match都没有在各自的可搜索块中包含所有这些字段,因此没有一条记录可以匹配您指定的条件。
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.
在这里,我们告诉Sunspot将配置文件匹配关联的属性编入索引,就好像它们存在于配置文件本身一样。在各个块中,我们告诉Sunspot如何在索引配置文件时填充这些值。
This will allow you to write your search using only the Profile
model:
这将允许您仅使用Profile模型编写搜索:
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.
请注意,在索引模型时会增加复杂性。如果匹配记录发生更改,则现在需要重新编制其关联的配置文件以反映这些更改。
#2
4
This is what i am doing when i have to search for multiple models
当我必须搜索多个模型时,这就是我正在做的事情
Sunspot.search [Model1, Model2] do
....
end
#3
4
@moises-zaragoza answered correctly your question but you have more issues than you think with what you want to do.
@ moises-zaragoza正确回答了你的问题,但是你遇到的问题比想象的要多。
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?
最有可能产生因为params [:age_from]和/或params [:age_to]为零。我无法保证,因为您没有显示堆栈跟踪。只有当它们存在时你才可以通过过滤器来修复:with(:age).between(params [:age_from] .. params [:age_to])if params [:age_from] .present?和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):
与您的观点相关。我假设你正在使用rails helper部分对象助手之一渲染一个集合或对象,而没有指定部分(再次,没有代码,这比其他任何东西都更好):
<%= 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.
当Rails没有指定部分时,它会根据对象类型猜测部分名称。在这种情况下,如果您的对象是类Educator的示例,它可能是Profile的子类,Rails将查找部分'educators / _educator.html.erb。确保根据对象类型呈现正确的部分,这将确保您呈现所需的内容。
#4
2
Here the answer for search different model on matching string using with
这里是使用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
#1
7
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 thesecountry
andstate
values, and whoseMatch
record has thislooking_for_education
value向我提供包含这些国家/地区和州值的所有个人资料记录,其匹配记录具有此looking_for_education值
Your search, however, says:
但是,您的搜索说:
Give me all records of type
Profile
orMatch
that have all of thesecountry
,state
andlooking_for_education
values给我所有类型为Profile或Match的记录,其中包含所有这些country,state和looking_for_education值
Because neither Profile
nor Match
have all of these fields in their respective searchable
blocks, no single record can match the conditions you specify.
由于Profile和Match都没有在各自的可搜索块中包含所有这些字段,因此没有一条记录可以匹配您指定的条件。
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.
在这里,我们告诉Sunspot将配置文件匹配关联的属性编入索引,就好像它们存在于配置文件本身一样。在各个块中,我们告诉Sunspot如何在索引配置文件时填充这些值。
This will allow you to write your search using only the Profile
model:
这将允许您仅使用Profile模型编写搜索:
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.
请注意,在索引模型时会增加复杂性。如果匹配记录发生更改,则现在需要重新编制其关联的配置文件以反映这些更改。
#2
4
This is what i am doing when i have to search for multiple models
当我必须搜索多个模型时,这就是我正在做的事情
Sunspot.search [Model1, Model2] do
....
end
#3
4
@moises-zaragoza answered correctly your question but you have more issues than you think with what you want to do.
@ moises-zaragoza正确回答了你的问题,但是你遇到的问题比想象的要多。
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?
最有可能产生因为params [:age_from]和/或params [:age_to]为零。我无法保证,因为您没有显示堆栈跟踪。只有当它们存在时你才可以通过过滤器来修复:with(:age).between(params [:age_from] .. params [:age_to])if params [:age_from] .present?和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):
与您的观点相关。我假设你正在使用rails helper部分对象助手之一渲染一个集合或对象,而没有指定部分(再次,没有代码,这比其他任何东西都更好):
<%= 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.
当Rails没有指定部分时,它会根据对象类型猜测部分名称。在这种情况下,如果您的对象是类Educator的示例,它可能是Profile的子类,Rails将查找部分'educators / _educator.html.erb。确保根据对象类型呈现正确的部分,这将确保您呈现所需的内容。
#4
2
Here the answer for search different model on matching string using with
这里是使用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