如何在同一模型上组合两个查询的结果?

时间:2011-03-23 21:13:29

标签: ruby-on-rails ruby-on-rails-3

我需要返回十个记录才能在视图中使用。我有一个高度限制性的查询我想使用,但我想要一个限制较少的查询来填写结果,以防第一个查询没有产生十个结果。

只是玩了几分钟,这就是我想出来的,但它不起作用。我认为它不起作用,因为合并意味着在不同模型上组合查询,但我可能是错的。

class Article < ActiveRecord::Base
...
  def self.listed_articles
    Article.published.order('created_at DESC').limit(25).where('listed = ?', true)
  end

  def self.rescue_articles
    Article.published.order('created_at DESC').where('listed != ?', true).limit(10)
  end

  def self.current
    Article.rescue_articles.merge(Article.listed_articles).limit(10)
  end
...
end

在控制台中查看,这会强制查询rescue_articles中查询中的lists_articles限制,显示如下内容:

Article Load (0.2ms)  SELECT `articles`.* FROM `articles` WHERE (published = 1) AND (listed = 1) AND (listed != 1) ORDER BY created_at DESC LIMIT 4
Article Load (0.2ms)  SELECT `articles`.* FROM `articles` WHERE (published = 1) AND (listed = 1) AND (listed != 1) ORDER BY created_at DESC LIMIT 6 OFFSET 4

我确信在文档中我遗漏了一些非常简单的方法,但我还没有找到它。

编辑: 我想要做的是返回最近25篇文章中列出的所有文章。如果这不能得到我的十篇文章,我想在最近的文章中添加足够的文章,列出的不是真的,以获得我的十篇文章。

编辑#2:编辑#2: 换句话说,merge方法似乎将查询串在一起以进行一次长查询而不是合并结果。我需要两个查询的前十个结果(列出所列文章的优先级),而不是一个长查询。

4 个答案:

答案 0 :(得分:11)

使用您的初始代码:

您可以使用+加入两个数组,然后获得前10个结果:

  def self.current
    (Article.listed_articles  +  Article.rescue_articles)[0..9]
  end

我认为这样做的方法很简单:

  def self.current
      oldest_accepted = Article.published.order('created_at DESC').limit(25).last
      Artcile.published.where(['created_at > ?', oldest_accepted.created_at]).order('listed DESC').limit(10)
  end

答案 1 :(得分:2)

您需要做的就是总结查询:

result1 = Model.where(condition)
result2 = Model.where(another_condition)

# your final result
result = result1 + result2

答案 2 :(得分:2)

如果您想要bundle.getType()对象而不是数组,可以使用:

  • ActiveRecordUnion gem

    安装gem:ActiveRecord::Relation并使用:

    gem install active_record_union
  • UnionScope module

    创建模块UnionScope(lib / active_record / union_scope.rb)。

    def self.current
      Article.rescue_articles.union(Article.listed_articles).limit(10)
    end
    

    然后在你的文章模型中调用它。

    module ActiveRecord::UnionScope
      def self.included(base)
        base.send :extend, ClassMethods
      end
    
      module ClassMethods
        def union_scope(*scopes)
          id_column = "#{table_name}.id"
           if (sub_query = scopes.reject { |sc| sc.count == 0 }.map { |s|   "(#{s.select(id_column).to_sql})" }.join(" UNION ")).present?
            where "#{id_column} IN (#{sub_query})"
          else
            none
          end
        end
      end
    end
    

答案 3 :(得分:0)

我认为你可以在一个查询中完成所有这些:

 Article.published.order('listed ASC, created_at DESC').limit(10)

我可能在列出的列上排序顺序错误,但实质上这应该有效。您将首先获得所有列出的项目,按created_at DESC排序,然后按未列出的项目排序。