处理ActiveRecord带有三种连接类型的where子句的最佳方法

时间:2018-11-05 20:18:12

标签: ruby-on-rails postgresql activerecord

查找所有具有与某些属性ID匹配的子项的对象的最佳方法是什么?

采用以下模型:

顶级型号:

class InstagramPost < ApplicationRecord
  has_many :instagram_post_hashtags
  has_many :instagram_post_mentions
  has_many :instagram_post_locations
end

class InstagramHashtag < ApplicationRecord
  has_many :instagram_post_hashtags
  has_many :instagram_posts, through: :instagram_post_hashtags
end

class InstagramMention < ApplicationRecord
  has_many :instagram_post_mentions
  has_many :instagram_posts, through: :instagram_post_mentions
end

class InstagramLocation < ApplicationRecord
  has_many :instagram_post_locations
  has_many :instagram_posts, through: :instagram_post_locations
end

加入:

class InstagramPostHashtag < ApplicationRecord
  belongs_to :instagram_hashtag
  belongs_to :instagram_post
end

class InstagramPostLocation < ApplicationRecord
  belongs_to :instagram_location
  belongs_to :instagram_post
end

class InstagramPostMention < ApplicationRecord
  belongs_to :instagram_mention
  belongs_to :instagram_post
end

现在说我有三个ID数组:

instagram_hashtag_ids = [12,20,23]
instagram_location_ids = [4,12,30]
instagram_mention_ids = [121,21,31]

如果我想查找具有InstagramPostInstagramPostHashtagInstagramPostLocation必须与上述所有数组ID匹配的所有InstagramPostMention;我以为我可以做类似的事情:

@instagram_posts = InstagramPost.joins(:instagram_post_hashtags).where("instagram_post_hashtags.instagram_hashtag_id IN (#{instagram_hashtag_ids})")

然后获取这些结果,并在下一个数组上进行搜索:

@instagram_posts = @instagram_posts.joins(:instagram_post_locations).where("instagram_post_locations.instagram_location_id IN (#{instagram_location_ids})")

以此类推...

这似乎是一种非常糟糕的方法,因为如果数组中没有ID,它将返回为空。实际上,即使所有数组中都有ID,并且有数据可以反映出来(大多数情况下是PostgreSQL的问题?),但大多数情况下它没有返回任何结果。

查询InstagramPost的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

要获取所有具有与给定ID数组匹配的联接表的InstagramPost

@instagram_posts = InstagramPost.joins(
  :instagram_post_hashtags,
  :instagram_post_mentions,
  :instagram_post_locations
).where(
  instagram_post_hashtags: { instagram_hashtag_id: instagram_hashtag_ids },
  instagram_post_locations: { instagram_location_id: instagram_location_ids }, 
  instagram_post_mentions: { instagram_mention_id: instagram_mention_ids }
)