3

Solr を検索エンジンとして使用する Ruby on Rails アプリケーションを作成しています。次のバージョン番号は、次の段落で説明する問題に関連している可能性があります。

  • ルビー: 1.9.2
  • レール: 3.2.6
  • 黒点: 1.3.0.rc5

バックグラウンド

Feedback異なるサブクラスに継承されるモデルがあります。クラス階層は次のようになります (単一テーブルの継承)。

Feedback
  |- Problem
  |- Question
  |- Suggestion
  |- Announcement

モデルではFeedback、次のコードによってインデックス作成が有効になります。

searchable :auto_index => true, :auto_remove => true do
  string :type
  text :title, :boost => 2
  text :content
  integer :user_id
  time :created_at
  ...
end

問題

これに関する問題は、たとえば、Problem"problemtitle" というタイトルの新しい を作成するときに、Sunspot がProblem および基礎となるの自動索引付けを初期化することFeedbackです。「problemtitle」というタイトルのフィードバックを検索すると、

search = Feedback.solr_search do
    with(:type, type.capitalize)
    fulltext("problemtitle") {minimum_match 1}
    paginate(page: options[:page], per_page: options[:per_page])
end

2 つの結果が見つかりました。1 つの結果はProblemで、もう 1 つはFeedbackです。これは、クラス階層でクラスとそのサブクラスがインデックス付けされていることを示します。私が知る限り、これは正しいはずです。

ここで奇妙なことは、コマンドでインデックスを再インデックスし、タイトル「problemtitle」bundle exec rake sunspot:solr:reindexで検索すると、上記で作成されFeedbackた 1 つの結果が得られることです。Problem

モデル:unless => proc {|model| model.class == Feedback}内の検索可能な定義に追加することで、これを解決しました。Feedbackこれにより、 のサブクラスのみFeedbackが自動的にインデックス付けされます。

質問

私の質問は、これが望ましい動作であるかどうかです(機能またはバグですか)。再インデックス付けが、作成時の自動インデックス付けとは異なる方法でモデルのインデックス付けを処理する理由がわかりません。これは、クラス階層の実装方法の問題でしょうか?

私の質問に答えるためにさらに情報が必要な場合は、それを提供しようとします。

敬具、

セバスチャン

4

2 に答える 2

4

Sebastian さん、ここでの問題は、Sunspot が完全なクラス名と ID を使用して Solr プライマリ ID を作成することだと思います。

def index_id_for(class_name, id) #:nodoc:
  "#{class_name} #{id}"
end

そのため、クラスが としてインデックス付けされ、Feedback次に Solr としてインデックス付けされている場合、Feedback::ProblemSolr には 2 つのエントリが含まれるため、検索時に両方が返されます。次に、Sunspot はそれぞれをデータベースと照合し、同じアイテムを 2 回取得します。インデックスを再作成すると、データベース全体が削除され、すべてのアイテムが現在のクラスでインデックスが作成されます。これが、インデックスを再作成した後に 1 つしかない理由です。

同様の問題がありました。解決策は、InstanceAdapterSTI クラス用に独自の を作成し、それを初期化子に登録することでした。

class StiInstanceAdapter < Sunspot::Adapters::InstanceAdapter

  def id
    @instance.id
  end

  def index_id
    return Sunspot::Adapters::InstanceAdapter.index_id_for(@instance.class.base_class.name, id)
  end

end

Sunspot::Adapters::InstanceAdapter.register(StiInstanceAdapter, Feedback)

これが少し遅れていることはわかっていますが、うまくいけば役に立ちます。

于 2014-05-23T16:41:13.137 に答える