Rails 5中基于belongs_to关联表的ActiveRecord查询问题
在Rails中通过关联的Spec表的broker字段筛选Listing
嘿,这事儿不难搞定!既然你的Listing模型和Spec模型是belongs_to关联(也就是Listing关联到一个Spec,类似评论属于某篇博客),我们可以通过ActiveRecord的关联查询来实现你的需求,对应你已经有的Spec查询,我给你一一对应写出Listing的查询语句:
1. 对应Spec.where(mls:"1234566"):找关联Spec的mls为1234566的Listing
如果你想获取所有关联的Spec满足mls: "1234566"的Listing,用joins关联表后筛选就行:
@listings = Listing.joins(:spec).where(specs: { mls: "1234566" })
这里注意表名是复数specs(ActiveRecord默认用复数表名),如果你的表名不是这个,要改成实际的表名。
2. 对应Spec.where('broker @> array[?] ',['%joe%','%bob%']):找关联Spec的broker匹配指定值的Listing
看你的查询语法,应该是在处理PostgreSQL的数组字段或者模糊匹配,分两种情况调整:
- 如果broker是数组字段,要匹配包含
joe/bob的数组:
@listings = Listing.joins(:spec).where('specs.broker @> array[?]', ['joe', 'bob'])
- 如果broker是字符串字段,要模糊匹配包含
joe/bob的记录:
@listings = Listing.joins(:spec).where('specs.broker LIKE ANY (array[?])', ['%joe%', '%bob%'])
如果你的原Spec查询语法是验证过可用的,直接把条件加上表名前缀specs.也能行:
@listings = Listing.joins(:spec).where('specs.broker @> array[?]', ['%joe%', '%bob%'])
3. 对应Spec.distinct(:broker).limit(50).order(broker: :asc):获取关联Spec的broker去重后的Listing
如果你想获取拥有不同broker的Listing,并且按broker升序取前50个,可以这么写:
@listings = Listing.joins(:spec).distinct('specs.broker').order('specs.broker ASC').limit(50)
要是你需要先拿到去重的broker列表再查对应的Listing,也可以分两步操作:
# 先获取去重的前50个broker unique_brokers = Spec.distinct(:broker).limit(50).order(broker: :asc).pluck(:broker) # 再找关联这些broker的Listing @listings = Listing.joins(:spec).where(specs: { broker: unique_brokers })
贴合你原本的需求:筛选后取最后4条Listing
如果你需要像原来那样获取筛选后的最后4个Listing,只需要在查询语句末尾加上.last(4)就行,比如:
# 示例:筛选broker包含joe/bob的Listing后取最后4个 @listings = Listing.joins(:spec).where('specs.broker LIKE ANY (array[?])', ['%joe%', '%bob%']).last(4)
额外提示:避免N+1查询
如果之后你要遍历Listing并访问其关联的Spec数据,建议用includes代替joins来预加载关联,减少数据库查询次数:
@listings = Listing.includes(:spec).where(specs: { mls: "1234566" })
这样在处理每个Listing的Spec时,不会触发额外的数据库查询。
内容的提问来源于stack exchange,提问作者Boucherie
相关产品推荐
相关产品推荐

