使用Sunspot / Solr的团体?

使用太阳黑子时我在按组搜索时遇到问题。

这是一个例子:

# == Schema Information # # Table name: movies # # id :integer(4) not null, primary key # title :string(255) class Movie < ActiveRecord::Base has_and_belongs_to_many :actors searchable do text :title integer :ages, multiple: true do actors.map(&:age) end text :names, multiple: true do actors.map(&:name) end end end # == Schema Information # # Table name: actors # # id :integer(4) not null, primary key # name :string(255) # age :integer(30) class Actor < ActiveRecord::Base has_and_belongs_to_many :movies searchable do integer :age text :name end end 

我想找一部30岁时有一个名叫约翰的演员的电影。

 Movie.search do with(:names).equal_to("John") with(:ages).equal_to(30) with(:title).equal_to("...") # ... end 

问题在于它可能会找到一部有两个演员的电影; 一个名叫约翰的人和一个30岁的人。有没有办法以某种方式将这个组合在一起,以便发现这部电影在30岁时有一个名叫约翰的演员?

正如MaurícioLinhares在评论中写道的那样,解决方案是通过电影来完成演员模型和小组。

问题是Sunspot不支持Solr 3.3或4.0,这是唯一支持分组的Solr版本。

这是我使用Sunspot 1.2.1和Solr 3.3的解决方案。

在我的示例中, movie_id被放置在actors表中,这不是在我的实际应用程序中完成的。

 # == Schema Information # # Table name: actors # # id :integer(4) not null, primary key # name :string(255) # created_at :datetime # updated_at :datetime # movie_id :integer(4) # class Actor < ActiveRecord::Base searchable do # We need to store the movie_id as an string # So it can be sorted. We also need to pass the # stored: true params string :movie_id, stored: true do movie_id.to_s end end def search_using_solr scoped = Sunspot.new_search(Actor) scoped.build do adjust_solr_params do |params| params[:group] = true params[:"group.field"] = "movie_id_s" params[:"group.format"] = "simple" end end # Sunspot 1.2.1 doesn't support grouping, so we need to do some hacking. def scoped.hits @hits ||= @solr_result["grouped"].values.first["doclist"]["docs"].map do |doc| Sunspot::Search::Hit.new(doc, nil, self) end end def scoped.total @total ||= @solr_result["grouped"]["movie_id_s"]["matches"] || 0 end # Here we'll only fetch the stored data from Solr it self, # and then pass it manualy to ActiveRecord. Movie.where({ id: scoped.execute.hits.map{ |h| h.stored(:movie_id) } }) end end 

感谢alindeman的榜样 。