Rails 中的多个查询条件 - 如果它们存在。

Posted

技术标签:

【中文标题】Rails 中的多个查询条件 - 如果它们存在。【英文标题】:Multiple query conditions in Rails - if they exist. 【发布时间】:2013-07-05 08:11:29 【问题描述】:

我在这里搜索时发现了一些类似的问题,但是当我尝试在我找到的解决方案中添加 unless 时,事情开始出现问题......

这是我所拥有的:

控制器:

    @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) unless @screen.current_ratio_min.nil?

一旦我添加了另一个 .where 行(我需要添加很多行),

    @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) unless @screen.current_ratio_min.nil?
    .where("current_ratio < ?", @screen.current_ratio_max) unless @screen.current_ratio_max.nil?

我收到一个错误:

undefined method `where' for false:FalseClass

我假设这是因为第一个除非正在结束我的查询。如何将除非仅应用于每个单独的条件?如果那是,事实上,问题:\

提前致谢!

【问题讨论】:

在相关部分,我发现***.com/questions/9308820/… 解决了我的问题,我想......我想如果你不知道要搜索什么,那么很难找到你正在寻找的东西为! 【参考方案1】:

这样的事情呢?

if !@screen.current_ratio_min.nil? && !@screen.current_ratio_max.nil?
  @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min).where("current_ratio < ?", @screen.current_ratio_max)
elsif @screen.current_ratio_min.nil? && !@screen.current_ratio_max.nil?
  @metrics = Metric.where("current_ratio < ?", @screen.current_ratio_max)
elsif !@screen.current_ratio_min.nil? && @screen.current_ratio_max.nil?
  @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min)
else
  @metrics = Metric.all
end

【讨论】:

我没有像我应该的那样清楚。有人可以输入最小值,但将最大值留空。在这种情况下,我只想搜索大于最小值。如果这有意义的话。 如果他有一些可选的过滤器,这将变得非常混乱。【参考方案2】:
@metrics = Metric.all
@metrics = @metrics.where('current_ratio > ?', @screen.current_ration_min) if @screen.current_ratio_min.present?
@metrics = @metrics.where('other_value > ?', @screen.other_value) if @screen.other_value.present?

这是我能想到的最好的方法,无需以编程方式构建可能存在 SQL 注入风险的 where 子句字符串。

继续添加尽可能多的条件。值得注意的是,使用 if something.present?而不是你的 unless something.nil?

此外,Metric.all 可能并不理想,但无论您需要什么来获取所有记录。

【讨论】:

这仅适用于 rails 4,在 rails 3 中都执行查询并返回一个数组(您可以在 rails 3 中使用 scoped 代替) 谢谢!这比我想做的要干净得多。并且看起来更具可扩展性!感谢大家,显然这是一个比我想象的更复杂的问题!很多好主意:) 在 Rails4 中,会执行多少 SQL 选择? 3次 ?还是只有一次? 得到我的问题的答案,rails 会懒惰评估,所以它只会是一个数据库查询。【参考方案3】:

试试下面的代码

if @screen.current_ratio_min and @screen.current_ratio_max
  @metrics = Metric.where("current_ratio > ? and current_ratio < ?", @screen.current_ratio_min, @screen.current_ratio_max)
else
 unless @screen.current_ratio_min.blank?
   @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min)
 else
   unless @screen.current_ratio_max.blank?
     @metrics = Metric.where("current_ratio < ?", @screen.current_ratio_max)
   else
     @metrics = Metric.all
   end
 end 
end

【讨论】:

想象一下,当您再添加一个可选参数时,这段代码的样子。 Joel,它正在根据条件获取有限的记录。如果我们先获取所有记录,然后我们将对其应用条件,这意味着对于每个条件,我们需要先获取所有记录,可以通过这种方式进行优化:)。 确实,我的选项没有为查询优化,但是如果使用更多参数,此代码将无法使用。如果他们需要优化,我认为他们需要以编程方式构建查询。我不会以牺牲代码可维护性为代价过早地进行优化。【参考方案4】:

如果你想要干净的代码,请使用scope

在metric.rb中

  scope :current_ratio_min, lambda |current_ratio_min|
    current_ratio_min.present? ? where('current_ratio > ?', current_ration_min) : where()
  scope :current_ratio_max, lambda |current_ratio_max|
    current_ratio_max.present? ? where('current_ratio > ?', current_ratio_max) : where()

您的查询:

@metrics = Metric.current_ratio_min(@screen.current_ratio_min).current_ratio_max(@screen.current_ratio_max)`

【讨论】:

【参考方案5】:

在 Array 类中编写以下方法

 class Array
  def add_condition!(condition, conjunction = 'AND')
   if String === condition
     add_condition!([condition])
   elsif Hash === condition
     add_condition!([condition.keys.map  |attr| "#attr=?" .join(' AND ')] + condition.values)
   elsif Array === condition
     unless condition.empty?
       self[0] = "(#self[0]) #conjunction (#condition.shift)" unless empty?
       self.push(*condition)
     end
   else
    raise "don't know how to handle this condition type"
   end
  self
 end
end

您可以为 ActiveRecord where 或 find 建立条件,如下所示

 conditions = []
 conditions.add_condition!(["current_ratio > ?", @screen.current_ratio_min]) unless @screen.current_ratio_min.nil?  
 conditions.add_condition!(["current_ratio < ?", @screen.current_ratio_max]) unless @screen.current_ratio_max.nil?
 @metrics = Metric.where(conditions)

这将有助于使用 AND/OR 组合构建多个条件

【讨论】:

以上是关于Rails 中的多个查询条件 - 如果它们存在。的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL查一个字段中 多个值

如何查询API函数 在知道中文意思的情况下如何查英文的API函数

搜索系统7:索引查询方法与评价方法

sql查询语句如何能把不符合条件的数据也一并查出来

IF 条件返回太多值

Mysql数据库连接查询