太阳黑子solr如何正确搜索多个模型?所有在线示例均失败

时间:2022-09-01 22:13:14

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 these country and state values, and whose Match record has this looking_for_education value

向我提供包含这些国家/地区和州值的所有个人资料记录,其匹配记录具有此looking_for_education值

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

给我所有类型为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 these country and state values, and whose Match record has this looking_for_education value

向我提供包含这些国家/地区和州值的所有个人资料记录,其匹配记录具有此looking_for_education值

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

给我所有类型为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