搜索多列 - Rails

发布于 2025-01-07 20:40:49 字数 538 浏览 0 评论 0原文

我目前正在为我的 Rails 应用程序编写一个搜索方法,目前它运行良好。我的 game.rb 中有以下内容:

def self.search(search)
  if search
    find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "#{search}", "#{search}"])
  else
    find(:all)
  end
end

现在搜索正常,但我的问题是,如果 game_name 中有一条记录包含“playstation”一词,它将在那里完成搜索。它仅返回该记录,而不返回控制台中存储有“PlayStation”的所有游戏。现在我明白这是因为我的条件中有“OR”,但我不知道还有什么选择。 “AND”要求所有条件都匹配,否则根本不返回。我可以用什么替代 AND 和 OR?非常感谢您的帮助。

如果有一个解决方案具有单独的搜索框和条目,那么那就没问题,我不一定要求搜索基于一个搜索表单来查找所有内容。

I am currently writing a search method for my rails applications, and at the moment it works fine. I have the following in my game.rb:

def self.search(search)
  if search
    find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "#{search}", "#{search}"])
  else
    find(:all)
  end
end

Now that searches fine, but my problem is that if there is a record in game_name that has the word 'playstation' in it, it will finish the search there. It only returns that record, rather than all games that have 'playstation' stored in console. Now I understand this is because I have 'OR' in my conditions, but I don't know an alternative. 'AND' requires all the conditions to match or none return at all. What is an alternative I can use to AND and OR? Help would be much appreciated.

If there is a solution that has separate search boxes and entries, then that would be fine, I don't necessarily require the search to find it all based on one search form.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浅笑轻吟梦一曲 2025-01-14 20:40:49

如果我正确理解你的问题,你的 SQL 对我来说看起来很适合你想要做的事情。 OR 子句将返回在column1、column2 或column3 中匹配的所有记录。它不会在第一场比赛就停止。我确实看到您的参数存在问题,因为第一个参数使用 LIKE 与 % 但在后两个参数中则没有,也许这就是您的问题所在。

这应该是您的发现(第二次和第三次搜索的百分比)?

find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])

或者更好地使用 DRY 版本(以上不适用于 Rails 4.2+):

Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: "%#{search}%")

If I understand your question correctly, your SQL looks good to me for what you are trying to do. An OR clause will return all records that match in column1, column2, or column3. It doesn't stop at the first match. I do see an issue with your parameters in that the first you are using LIKE with % but in the second two you aren't, maybe that is where your issue is coming from.

Should this be your find (% around second and third search)?

find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])

or better use DRY version (above will not work for Rails 4.2+):

Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: "%#{search}%")
╰つ倒转 2025-01-14 20:40:49

如果您有 15 列要搜索,那么您将重复 key 15 次。您可以这样编写,而不是在查询中重复键 15 次:

key = "%#{search}%"

@items = Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: key).order(:name)

它将给出相同的结果。

谢谢

What if you have 15 columns to search then you will repeat key 15 times. Instead of repeating key 15 times in query you can write like this:

key = "%#{search}%"

@items = Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: key).order(:name)

It will give you same result.

Thanks

淑女气质 2025-01-14 20:40:49

我认为这是一个更干净的解决方案。这使您可以更轻松地添加/删除列。

key = "%#{search}%"
columns = %w{game_name genre console}
@items = Item.where(
  columns
    .map {|c| "#{c} like :search" }
    .join(' OR '),
  search: key
)

I think this is a little bit of a cleaner solution. This allows you to add/remove columns more easily.

key = "%#{search}%"
columns = %w{game_name genre console}
@items = Item.where(
  columns
    .map {|c| "#{c} like :search" }
    .join(' OR '),
  search: key
)
清君侧 2025-01-14 20:40:49

在模型的所有字段中进行搜索的更通用的解决方案将是这样的

def search_in_all_fields model, text
  model.where(
    model.column_names
      .map {|field| "#{field} like '%#{text}%'" }
      .join(" or ")
  )
end

或者更好的是作为模型本身的范围

class Model < ActiveRecord::Base
  scope :search_in_all_fields, ->(text){
    where(
      column_names
        .map {|field| "#{field} like '%#{text}%'" }
        .join(" or ")
    )
  }
end

您只需要像这样调用它

Model.search_in_all_fields "test"

在开始之前..,不,sql 注入可能在这里不起作用,但是仍然更好更短

class Model < ActiveRecord::Base
  scope :search_all_fields, ->(text){
    where("#{column_names.join(' || ')} like ?", "%#{text}%")
  }
end

A more generic solution for searching in all fields of the model would be like this

def search_in_all_fields model, text
  model.where(
    model.column_names
      .map {|field| "#{field} like '%#{text}%'" }
      .join(" or ")
  )
end

Or better as a scope in the model itself

class Model < ActiveRecord::Base
  scope :search_in_all_fields, ->(text){
    where(
      column_names
        .map {|field| "#{field} like '%#{text}%'" }
        .join(" or ")
    )
  }
end

You would just need to call it like this

Model.search_in_all_fields "test"

Before you start.., no, sql injection would probably not work here but still better and shorter

class Model < ActiveRecord::Base
  scope :search_all_fields, ->(text){
    where("#{column_names.join(' || ')} like ?", "%#{text}%")
  }
end
剪不断理还乱 2025-01-14 20:40:49

如果您想像我一样搜索列数组,我认为这是一个更有效的解决方案。

首先也是最重要的是,您可以向模型添加一个私有函数来创建查询模板:

def self.multiple_columns_like_query(array)
  array.reduce('') { |memo, x|  #
    unless memo == ''           #
      memo += ' or '            #  This is the
    end                         #  
    memo += "#{x} like :q"      #  core part
  }                             #
end                             

您可以在搜索函数中使用该函数:

def self.search(query)
  if fields = self.searched_fields && query
    where multiple_like_query(fields), q: "%#{query}%"
  end
end

在这里您还应该将 self.searched_fields 定义为字段数组名称。

I think this is a more efficient solution if you want to search an array of columns as I do.

First and most importantly you can add a private function to your model that creates a query template:

def self.multiple_columns_like_query(array)
  array.reduce('') { |memo, x|  #
    unless memo == ''           #
      memo += ' or '            #  This is the
    end                         #  
    memo += "#{x} like :q"      #  core part
  }                             #
end                             

Than you can use the function in your search function:

def self.search(query)
  if fields = self.searched_fields && query
    where multiple_like_query(fields), q: "%#{query}%"
  end
end

Here you should also define self.searched_fields as an array of field names.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文