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

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

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

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:换句话说,合并方法似乎将查询串起来进行一次长查询而不是合并结果。 我需要两个查询的前十个结果(列出所列文章的优先级),而不是一个长查询。

使用您的初始代码:

您可以使用+连接两个数组,然后获得前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 

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

 result1 = Model.where(condition) result2 = Model.where(another_condition) # your final result result = result1 + result2 

如果需要ActiveRecord::Relation对象而不是Array,可以使用:

  • ActiveRecordUnion gem 。

    安装gem: gem install active_record_union并使用:

     def self.current Article.rescue_articles.union(Article.listed_articles).limit(10) end 
  • UnionScope模块 。

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

     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 

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

     class Article < ActiveRecord::Base include ActiveRecord::UnionScope ... def self.current union_scope(Article.rescue_articles, Article.listed_articles).limit(10) end ... end 

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

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

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