2015-04-06 59 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