2

Sunspot を使用しているときに、グループによる検索に問題があります。

次に例を示します。

# == 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

ここでの問題は、2 人の俳優がいる映画を見つける可能性があることです。1 人はジョンという名前で、もう 1 人は 30 歳でした。映画に 30 歳でジョンという名前の俳優がいることがわかるように、これを何らかの方法でグループ化する方法はありますか?

4

1 に答える 1

3

Maurício Linharesが彼のコメントで書いたように、解決策は、俳優モデルを調べて、映画ごとにグループ化することです。

問題は、グループ化をサポートする唯一の Solr バージョンである Solr 3.3 または 4.0 を Sunspot がサポートしていないことです。

Sunspot 1.2.1 と Solr 3.3 を使用した私のソリューションを次に示します。

私の例movie_idでは、アクター テーブルに配置されていますが、これは実際のアプリケーションでは行われません。

# == 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にクレジットされます。

于 2011-09-03T10:39:09.750 に答える