2015-04-06 62 views
0

在Rails 4应用程序,我有两个型号:Rails 4:连接vs包含:为什么嵌套关联有不同的结果?

商家的has_many:offering_specials

OfferingSpecial belongs_to的:商人

我想要检索所有打开的商人和他们的特殊产品(与STATUS_CODE: “OP”)

我尝试这样做:

@merchants = Merchant.joins(:offering_specials).where(offering_specials: { status_code: "OP" }) 

这是曲红霉素:

Merchant Load (0.4ms) SELECT `merchants`.* FROM `merchants` INNER JOIN `offering_specials` ON `offering_specials`.`merchant_id` = `merchants`.`id` WHERE `offering_specials`.`status_code` = 'OP' 

但它检索的所有提供特价商品,无论是打开( “OP”)和待定( “PN”)。

然而,使用包括工作:

@merchants = Merchant.joins(:offering_specials).where(offering_specials: { status_code: "OP" }) 

这只能检索到的开放提供特价。但看看更慢的查询:

SQL (19.9ms) SELECT `merchants`.`id` AS t0_r0, `merchants`.`name` AS t0_r1, `merchants`.`slug` AS t0_r2, `merchants`.`url` AS t0_r3, `merchants`.`summary` AS t0_r4, `merchants`.`description` AS t0_r5, `merchants`.`active_for_display` AS t0_r6, `merchants`.`active_for_offerings_by_merchant` AS t0_r7, `merchants`.`active_for_offerings_by_legatocard` AS t0_r8, `merchants`.`credit_limit` AS t0_r9, `merchants`.`search_location_code` AS t0_r10, `merchants`.`image_file_name` AS t0_r11, `merchants`.`image_file_size` AS t0_r12, `merchants`.`image_content_type` AS t0_r13, `merchants`.`image_updated_at` AS t0_r14, `merchants`.`logo_file_name` AS t0_r15, `merchants`.`logo_file_size` AS t0_r16, `merchants`.`logo_content_type` AS t0_r17, `merchants`.`logo_updated_at` AS t0_r18, `merchants`.`created_at` AS t0_r19, `merchants`.`updated_at` AS t0_r20, `offering_specials`.`id` AS t1_r0, `offering_specials`.`special_number` AS t1_r1, `offering_specials`.`merchant_id` AS t1_r2, `offering_specials`.`merchant_user_id` AS t1_r3, `offering_specials`.`nonprofit_percentage` AS t1_r4, `offering_specials`.`discount_percentage` AS t1_r5, `offering_specials`.`start_at` AS t1_r6, `offering_specials`.`end_at` AS t1_r7, `offering_specials`.`closed_at` AS t1_r8, `offering_specials`.`max_dollar_amount_for_offering` AS t1_r9, `offering_specials`.`max_dollar_amount_per_buyer` AS t1_r10, `offering_specials`.`status_code` AS t1_r11, `offering_specials`.`created_at` AS t1_r12, `offering_specials`.`updated_at` AS t1_r13 FROM `merchants` LEFT OUTER JOIN `offering_specials` ON `offering_specials`.`merchant_id` = `merchants`.`id` WHERE `offering_specials`.`status_code` = 'OP' 

我怎样才能得到这个查询使用连接,而不是包括?

回答

0

这类查询通常不会返回相关记录。你正在申请一个商家名单,这就是你得到的。当您随后请求其中一个商家的相关OfferSpecials时,会执行一个新的查询(您应该在日志中看到该查询),并且您可以获得所有这些查询,因为您没有另行指定。您的问题中的代码不包括您执行此操作的位置,但您必须在某处执行此操作,以获取OfferSpecials。

使用includes要求加载关联,这意味着它将受到查询的限制,这就是为什么当你这样做时你看到它工作。速度较慢,因为它现在为您提供了这些额外的记录,而不是稍后分开进行。

如果你真的不想要这个使用.joins重构,你只需要在有条件的地方,您将获取商户的.offering_specials添加到行:

@merchants.each do |m| 
    m.offering_specials.where(:status_code => 'OP') 
end 

但是,你应该为什么急于阅读起来在这样做之前存在装载 - 很可能您或许已经通过对较多快速查询执行一个较慢的查询来获得更好的性能,或者如果商家记录的数量通过一些阈值(这可能会也可能不会)发生,取决于你的应用程序的性质)。

+0

感谢您的回复。我的代码在索引操作中位于控制器中。在索引视图中,我有这个:<%@ merchants.each do | merchant | %><%= merchant.offering_specials.last.nonprofit_percentage%><% end %> – rjnash1 2015-04-06 05:02:46

+0

因此,如果在该视图的这一行中,在'.last'之前添加'.where(:status_code =>'OP')',您应该得到期望的结果。正如我所说,您正在为每个商家生成一个查询,因此请检查总页面加载时间以确保其实际速度更快。 – MrTheWalrus 2015-04-06 05:08:39

+0

我同意您的整体分析。在控制器中使用includes会更慢(19ms),但它比单独的条件查询(每次7ms)更快。但我发现了另一个问题。通过将包含条件添加到包含中,它不会检索商家,除非他们有特别的公开发行。鉴于我需要所有的商家,我最终在控制器中使用了这个:@merchants = Merchant.includes(:offering_specials),这在索引视图中显示:<%= merchant.offering_specials.where(offering_specials:{status_code:“OP” })。last.nonprofit_percentage%>谢谢ThWalrus先生 – rjnash1 2015-04-06 05:31:59