我的应用程序中有以下模型,它以多种方式与另一个模型相关
class XYZRelated < ActiveRecord::Base
belongs_to :xyz1, class_name: 'XYZ', foreign_key: 'xyz1_id'
belongs_to :xyz2, class_name: 'XYZ', foreign_key: 'xyz2_id'
end
此外,我已经进行了验证,确保xyz1_id != xyz2_id
,并且即使ID已被交换,两个ID [xyz1_id, xyz2_id]
的每个组合都是唯一的,即有一行[3,1]
}表示[1,3]
不允许其他行。
对于JSON API,我希望能够在相关模型中搜索一个XYZ_ID,并尽可能高效地返回另一个ID。
但是,我不知道我要搜索的ID是存储在xyz1_id还是xyz2_id中。因此,我希望将任意ID与xyz1_id和xyz2_id进行比较,如果它匹配一列,我将返回另一个(除非另一个为NULL,在这种情况下我不会返回匹配)。
目前我正在这样做:
def find_all_ids(xyz_id)
l = XYZRelated.where(xyz1_id: xyz_id).where.not(xyz2_id: nil)
.pluck(:xyz2_id).to_a
l.concat XYZRelated.where(xyz2_id: xyz_id).where.not(xyz1_id: nil)
.pluck(:xyz1_id).to_a
return l
end
我认为有更好的方法可以做到这一点,或者甚至是更好的布局数据库的方法,以避免这个问题。但是,我对高级SQL查询不太熟悉,在Rails文档中找不到任何内容。
我怎样才能更有效地做到这一点,以避免两个单独的查询和结果的连接?谢谢!
答案 0 :(得分:1)
这是两个单独的查询,您可以使用UNION来组合它们,但我不太确定触发单个查询与之间的性能差异 UNION 强>
以下内容使其显着简化
XYZRelated.where("xyz1_id = :xyz_id OR xyz2_id = :xyz_id", xyz_id: xyz_id)
.pluck(:xyz1_id, :xyz2_id).uniq.compact - [xyz_id]
说明 -
- 查询xyz1_id或xyz2_id设置为xyz_id的所有记录
- 将阵列展平(2d阵列为1d阵列)
- 删除重复项(大约一半的数组是xyz_id,因为每个匹配的记录至少有一个id = xyz_id)
- 删除NULL条目(这样您就不必关心“其他”id为NULL)
- 然后删除输入参数 xyz_id ,因为它显然会在数组中
醇>