Postgres 全文搜索使用 pg_search - include(:child_model) 破坏了 SQL,其中包含表'child_model'缺少 FROM 子句条目



我正在使用带有pg_search宝石的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

我得到的错误是"缺少表'邀请'的 FROM 子句条目。我尝试了很多不同的东西,包括:

  1. 将"包含"替换为"联接">
  2. 将 'include(:invites( 替换为 joins('LEFT JOIN "invites" on "invites" on "invites"。电子邮件" = "电子邮件" '(
  3. 更改.text_search和 .include 调用的顺序。
  4. 在控制器、模型、作用域和text_search函数定义中添加 Include 调用。

我不断收到相同的错误,当将联接调用与SQL一起使用时,它不会按邀请电子邮件进行过滤,并显示每个搜索结果的多次重复。

我只会删除 include(:invites(,因为text_search本身工作得很好。但我真的需要包括这个条件。

任何帮助将不胜感激。也许我只是弄错了我的 SQL 调用,但我也想了解为什么 .include(:invites( 在没有 pg text_search的情况下工作,但不能使用它。

编辑#1 - 更具体的问题

我认为这里有两个略有不同的问题。第一个似乎是将 gem 和"include(:invites("调用组合pg_search一些问题。第二个问题是我可以用来避免进行"include(:invites("调用的等效SQL语句是什么。我认为它应该是某种左联接,但我认为我做得不正确。在我的数据库中,笔记本has_many邀请,邀请具有属性"电子邮件"。我需要带有邀请的笔记本,这些笔记本的电子邮件等于current_user的电子邮件。

帮助其中任何一个都会很棒。

这是向我展示问题解决方案的链接:https://github.com/Casecommons/pg_search/issues/109

这是我的具体代码:

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

键是joins语句。 joins(:invites( 不起作用,include(:invites( 不起作用。完整的 SQL 语句是必需的:

joins('LEFT OUTER JOIN invites ON invites.notebook_id = notebooks.id')

我可以看到一个连接,但我看不到是什么使加入的邀请字段出现在 SELECT 语句中。我认为您可能需要像这样将邀请表中的字段添加到 select(( 中

  select('invites.*').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')
 }

最新更新