【问题标题】:Group using Sunspot/Solr?使用 Sunspot/Solr 组?
【发布时间】:2011-08-11 19:39:39
【问题描述】:

我在使用 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

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

【问题讨论】:

  • 您的配置文件中有一个选项可以控制您的条件如何使用OR 或AND 形成“where”子句(将其修改为 AND 以获得您想要的)
  • @Octopus-Paul 这不是问题。我可以使用all_of 块来实现您所说的。问题是一部电影可以有不止一个演员,这意味着它可能会找到一部演员在 30 岁时和另一部名叫约翰的电影。
  • 您在错误的地方搜索,您应该在寻找演员,因为您正在尝试寻找演员而不是电影。让你的 actor 模型可以通过 solr 搜索并在其上进行搜索。
  • @Maurício Linhares 我不确定我应该对一群演员做什么。最后,我仍然需要一个电影列表。
  • 跟我想一想,你想找到所有演员年龄在 30 岁并叫约翰的电影。如果您找到一位名叫约翰的 30 岁演员,他的所有电影都符合您的条件。

标签: ruby-on-rails ruby solr sunspot


【解决方案1】:

解决方案,就像Maurício Linhares在他的评论中写的那样,是通过演员模型和电影分组。

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

这是我使用 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 他的example gist。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多