3

pg_search gem で postgres 全文検索を使用しています。検索自体はうまく機能していますが、結果をさらにフィルタリングする必要があります。詳細は次のとおりです。

class Notebook < ActiveRecord::Base

 has_many :invites

 def self.text_search(query)
  if query.present?
   search(query)
  else
   scoped
  end

end

ノートブック コントローラ:

def index
 if params[:query].present?
  @notebooks = Notebook.text_search(params[:query]).includes(:invites).where("invites.email = :email OR notebooks.access = :access OR notebooks.access = :caccess OR notebooks.user_id = :uid", email: current_user.email, access: "open", caccess: "closed", uid: current_user.id)
 else
  @notebooks = Notebook.includes(:invites).where("invites.email = :email OR notebooks.access = :access OR notebooks.access = :caccess OR notebooks.user_id = :uid", email: current_user.email, access: "open", caccess: "closed", uid: current_user.id)
 end

表示されるエラーは、「テーブル 'invites' の FROM 句のエントリがありません」です。私は次のようなさまざまなことを試しました:

  1. 「含む」を「結合」に置き換える
  2. 'includes(:invites) を joins('LEFT JOIN "invites" ON "invites"."email" = "email" ') に置き換える
  3. .text_search と .includes 呼び出しの順序を変更します。
  4. コントローラー、モデル、スコープ、および text_search 関数定義に include 呼び出しを追加します。

同じエラーが発生し続けます。結合呼び出しを SQL で使用すると、招待メールでフィルタリングされず、各検索結果が複数回繰り返されます。

text_search 自体は問題なく機能しているため、 include(:invites) を削除するだけです。しかし、私は本当にこの条件を含める必要があります。

どんな助けでも大歓迎です。SQL呼び出しが間違っているだけかもしれませんが、.includes(:invites)がpg text_searchなしで機能するのに機能しない理由も理解したいと思います。

編集 #1 - より具体的な質問

ここには2つのわずかに異なる質問があると思います。1 つ目は、pg_search gem と 'includes(:invites)' 呼び出しの組み合わせに関する問題のようです。2 番目の質問は、'includes(:invites)' 呼び出しを避けるために使用できる同等の SQL ステートメントは何かということです。ある種のLEFT JOINであるべきだと思いますが、正しく作っているとは思いません。私のデータベースでは、ノートブックには多数の招待があり、招待には「メール」属性があります。current_user の電子メールと同じ電子メールを持つ招待状のノートブックが必要です。

これらのいずれかのヘルプは素晴らしいでしょう。

4

2 に答える 2

2

Here is the link that showed me the solution to my problem: https://github.com/Casecommons/pg_search/issues/109

Here is my specific code:

class Notebook < ActiveRecord::Base
 has_many :invites

 include PgSearch
 pg_search_scope :search, against: [:title],
  using: {tsearch: {dictionary: "english"}},
  associated_against: {user: :name, notes:[:title, :content]}

 scope :with_invites_and_access, lambda{ |c_user_email|
  joins('LEFT OUTER JOIN invites ON invites.notebook_id = notebooks.id').where('invites.email = ? OR notebooks.access = ? OR notebooks.access = ?', c_user_email, 'open', 'closed')
 }

 def self.text_search(query)
  if query.present?
   search(query).with_invites_and_access(current_user_email)
  else
   scoped
  end
 end
end

The key was the joins statement. joins(:invites) doesn't work, includes(:invites) doesn't work. The full SQL statement is required:

joins('LEFT OUTER JOIN invites ON invites.notebook_id = notebooks.id')
于 2013-10-15T21:01:52.847 に答える