说我有2个AR查询:
users = User.where(...)
users = [user1, user2, user3]
和
users = User.some_complicated_query
users = [user3, user4, user5]
说我希望方法返回:
all_users = [user1, user2, user3, user4, user5]
我该怎么做这个联盟?我在Rails 4上,所以我没有or
。
我希望用户3是唯一的,而不是在最终集中重复。
merge上的文档不是很好但我不认为这是我想要的吗?
答案 0 :(得分:0)
这取决于这些查询实际上是什么以及它们如何重叠。如果您正在寻找符合 条件的用户,则需要使用or
,因为@SteveCarey建议:
regular_users = User.not_admins
admin_users = User.admins
all_users = regular_users.or(admin_users)
这不会执行SQL UNION
,但结果在这些示例中将是相同的。如果您要加入来自多个子查询的数据,则只需要一个正确的UNION
,在这种情况下,您可以use Arel来处理此问题。
请注意,这与Ruby自己的union运算符完全不同,后者仅保留两个联合对象集中的项。如果您正在寻找该行为,您可以合并范围:
User.not_admins.admins
在这种情况下,正如您所看到的,它不会非常有用。 ;)
其他情况:
对于您正在考虑与相关模型进行比较的情况,您可以使用references(:other_things).merge(OtherThing.condition)
获得相当远的距离。
如果您希望从存储在不同表中的两个类似对象返回数据,则应考虑使用single table inheritance在启用结果时启用ActiveRecord以实例化正确的对象类型。
如果您想要来自两个不相关对象的数据,但是您想要合并数据以进行演示或类似,那么您真的想要执行两个查询并将结果合并到Ruby中:
posts = Posts.recent
events = Events.recent
news_feed_items = Set.new(posts) + events
news_feed_items.sort_by { |a,b| a.created_at <=> b.created_at }
答案 1 :(得分:0)
total_users = users1 | users2
或者
total_users = (users1 + users2).uniq
应该最有可能做到这一点。与@ Iceman的解决方案类似,但它产生了一个额外的查询,我不赞成。
另外,试试
users1 = User.where(...)
users2 = User.some_complicated_query.where.not(id: users1.pluck(:id))
new_users = users1 + users2
答案 2 :(得分:0)
但我需要返回AR关系,而不是数组。 - Jwan622
正如@SteveCarey建议的那样,你可以通过这个得到联盟:
users1 = User.where(...)
users2 = User.some_complicated_query
all_users = users1 | users2
然后进行额外的查询以获得AR关系:
all_users = User.where(id: all_users)
但使用or
会使其更简单。 (升级到Rails 5或安装rails_or gem以使用or
)
all_users = users1.or(users2)