【问题标题】:How to find has many records based on search field with OR condition如何根据带有 OR 条件的搜索字段查找有许多记录
【发布时间】:2017-10-27 20:11:10
【问题描述】:

我已经实现了一个搜索,它可以搜索来自不同列的记录,但是如果我在 has_many (categories) 表中搜索记录以使用相同的搜索字段进行类别名称搜索,则它不起作用。

我有这样的模型:

影响者:

has_many :influencer_categories, dependent: :destroy
has_many :categories, through: :influencer_categories

代码是:

控制器:

@influencers = Influencer.search(params)

型号:

def self.search(params)
      .includes(:categories)
      .where(search_all(params[:q]))
      .where("LOWER(categories.name) like '%#{params[:q].downcase}%'")
end

def self.search_all(criteria)
    if criteria.include?('@') && criteria.start_with?('@')
      criteria.split(' ').map {|criterion| "LOWER(username) like '%#{criterion.downcase.gsub('@', '')}%'"}.join(' OR ')
    elsif criteria.include?('#') && criteria.start_with?('#')
      criteria.split(' ').map {|criterion| "LOWER(bio) like '%#{criterion.downcase.gsub('#', '')}%'"}.join(' OR ')
    else
      "LOWER(full_name) like '%#{criteria.downcase}%' OR LOWER(username) like '%#{criteria.downcase}%' OR LOWER(bio) like '%#{criteria.downcase}%'"
    end
  end

输出错误是:

ActionView::Template::Error (PG::UndefinedTable: ERROR:  missing FROM-clause 
entry for table "categories"
LINE 1: ... '%food%' OR LOWER(bio) like '%food%') AND (LOWER(categories...

                                                             ^
: SELECT COUNT(*) FROM "influencers" WHERE (LOWER(full_name) like '%food%' OR 
LOWER(username) like '%food%' OR LOWER(bio) like '%food%') AND 
(LOWER(categories.name) like '%food%')):

也许我需要在我的情况中包含 OR 以获得所需的结果,因此对于 food 类别,所有具有 food 类别的影响者都会出现. 这就是我需要做的。

我相信这样的事情会奏效:

SELECT "influencers"."id" FROM "influencers" LEFT OUTER JOIN 
"influencer_categories" ON "influencer_categories"."influencer_id" = 
"influencers"."id" LEFT OUTER JOIN "categories" ON "categories"."id" = 
"influencer_categories"."category_id" WHERE (LOWER(full_name) like '%food%' OR 
LOWER(username) like '%food%' OR LOWER(bio) like '%food%' OR 
LOWER(categories.name) like '%food%')

【问题讨论】:

    标签: activerecord ruby-on-rails-5 rails-activerecord


    【解决方案1】:

    最后,下面的查询对我很有效:

    我需要在最后或查询的第一部分连接 has_many 部分。

    还需要references 以避免错误。

    def self.search(params)
       .includes(:categories)
       .where(search_all(params[:q])+" OR LOWER(categories.name) like 
    '%#{params[:q].downcase}%'")
       .references(:categories)
    end
    

    输出以下 SQL 查询:

    SELECT "influencers"."id" AS t0_r0, "influencers"."instagram_id" AS t0_r1, 
    "influencers"."full_name" AS t0_r2, "influencers"."username" AS t0_r3, 
    "influencers"."profile_picture" AS t0_r4, "influencers"."website" AS t0_r5, 
    "influencers"."bio" AS t0_r6, "influencers"."created_at" AS t0_r7, 
    "influencers"."updated_at" AS t0_r8, "influencers"."slug" AS t0_r9, 
    "influencers"."email" AS t0_r10, "influencers"."follower_count" AS t0_r11, 
    "influencers"."like_count" AS t0_r12, "influencers"."comment_count" AS t0_r13, 
    "influencers"."media_count" AS t0_r14, "influencers"."country" AS t0_r15, 
    "influencers"."state" AS t0_r16, "influencers"."city" AS t0_r17, 
    "categories"."id" AS t1_r0, "categories"."name" AS t1_r1, 
    "categories"."created_at" AS t1_r2, "categories"."updated_at" AS t1_r3 FROM 
    "influencers" LEFT OUTER JOIN "influencer_categories" ON 
    "influencer_categories"."influencer_id" = "influencers"."id" LEFT OUTER JOIN 
    "categories" ON "categories"."id" = "influencer_categories"."category_id" 
    WHERE (LOWER(full_name) like '%food%' OR LOWER(username) like '%food%' OR 
    LOWER(bio) like '%food%' OR LOWER(categories.name) like '%food%') AND 
    "influencers"."id" IN (188, 189)
    

    如果可以用更优雅的方式完成,请添加您的答案或 cmets。

    【讨论】:

      猜你喜欢
      • 2013-09-12
      • 2013-03-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多