Rails Rails 中对不同来源的 ActiveRecord 结果集进行合并查询与排序的问题

sail_lee · 2016年04月29日 · 最后由 sail_lee 回复于 2016年04月29日 · 3550 次阅读

一、应用场景:

因项目需要,要对分别在两个不同的遗留系统中的不同结构的表进行数据合并查询。需要支持排序和二次搜索。

二、预想方案:

由于数据位于两个不同的遗留系统,数据库连接的指向不同,且两个表的结构也不同,因此也无法直接使用 arel 和直接的 SQL 查询,只能分别从两个同的系统中获取数据结果集进行整合后进行 Array 操作。具体见以下代码:

# 在OA系统上的OaPerson
class OaPerson < ActiveRecord::Base
  establish_connection :oa_system
  self.abstract_class = true
end

# 在Agent系统上的Agent
class Agent < ActiveRecord::Base
  establish_connection :agent_system
  self.abstract_class = true
end

# 从两个不同的AR Model中获取结果集合并
@people = OaPerson.select(user_id,user_name) + Agent.select(agent_id as user_id, agent_name as user_name)

# 按user_name字段排序
@people.sort_by(&:user_name)

# 以key_word作模糊查询
@people.select {|p| user_name.include?(key_word)}

三、问题:

1、针对以上应用场景,预想的方案勉强可以实现要求的功能,但肯定性能不佳。请教各位先进,有更好的解决方案吗? 2、结果集数组如何实现倒序的排列?

有没有可能预先算好?

  1. 更好的解决方案就要更多的工作

方法一 做个多余的表去把 2 个 model 的数据放一块了。
比如 NewAgent(source_type, source_id,user_id, user_name,) 把需要排序的字段都缓存进去,以后 Agent 和 OaPerson 的增删改都要设置 after_commit 去更新 NewAgent 表。 然后你就这么排吧,如果你的查询还需要查更多的字段那么查询的字段也都要放到 NewAgent 里去,可分页,可查询,可排序 你说好用不好用,简单不简单?

方法二 用 ElasticSearch 做个全文搜索,把 2 个 model 的数据都放在第三方的一个 document 里,搜索 都根据 ElasticSearch 来搜。这个方案其实类似方法一 都是把 2 个数据源的数据放到一个地方去,然后排序查询。方法二呢 可能还需要你学习 ElasticSearch,学习成本略高,但是方案看起来比较优雅,不影响数据库。

方法三 在 Agent 里加个个字段 oa_person_id 把 OaPerson 里的数据都保存在 Agent 表里。然后想怎么排怎么排,缺点 1. 万一两个表有好多字段不同,把所有字段都放一个表里 略难看,2. 加了 oa_person_id,某些只要 Agent 的地方的代码要改

  1. 数组倒序排列? @people.sort_by(&:user_name).reverse

还有问题吗?

#2 楼 @yakjuly 谢谢提供的方案

对于方法一、方法三,解决的思路总体是想办法合并成一个表处理。这个我有想过,原来的想法是讲上述两个表的数据按一定规则合并到一个表,每天定期同步,这样只增加数据运维工作,对三个系统的影响应该最小。 对于方法二,我再搜索学习下。

#1 楼 @lithium4010 两个查询结果集合并,无法预先算好

用 Elasticsearch 的话其实可以更简单一些,两个 AR model 分别对应两个 ES 的 document type, 放在同一个 index 下,不需要引入第三个 document type.

需要 登录 后方可回复, 如果你还没有账号请 注册新账号