2014-08-29 40 views
1

我有兩個實體User和Place,並且它們之間具有多對多的關係,以便於用戶偏好某個地方的概念。有什麼解決方案可以避免Doctrine2中的聚合計數字段出現select(n + 1)問題?

作爲該功能的一部分,我希望Place實體包含一個字段,該字段可以爲我提供已收藏的用戶總數。我不需要用戶實體本身。

閱讀文檔,我找到了幾種解決方案,但我並不特別喜歡它們中的任何一種。

聚合字段

使用該溶液,我會簡單地爲收藏添加和刪除要更新的地點實體定義的整數字段。因此,該值不是即時計算的,而是作爲任何其他字段進行檢索。

我不喜歡這種方法,因爲存在併發性問題,並且使代碼中的管理變得不必要的複雜。

預先加載

使用這種方法,我會急切裝載的關係作爲一個雙向關聯,使得地方將加載已經收藏它作爲初始查詢過程的一部分的每個用戶實體。爲了計數,我只需要詢問其數量()。

這會導致查詢次數減少,但檢索的數據量太多,並且隨着時間的推移不能很好地擴展。

額外的延遲加載

這是我目前正在使用。它與Eager Loading解決方案類似,我確保這種關係是雙向的,只需向集合詢問其count(),但使用額外的懶惰獲取模式原則足夠智能,只需發出一個COUNT()查詢而不是檢索與Place實體關聯的整個用戶列表。

這裏的缺點是,如果我加載N Place實體,我需要N + 1個查詢,因爲每個Place將發出一個單獨的COUNT()查詢。

理想的解決方案

我的理想的解決辦法是找到一個方法來告訴學說執行第一查詢加載集合,然後第二個查詢加載集合中,然後爲ID的所有罪名在其各自的實體中填充字段。

我還沒有找到一種方法來做到這一點很容易。

有沒有人有任何這樣的例子,或者有其他解決方案來解決這個問題,我可能忽略?

回答

0

如果你知道如何在sql中編寫你的查詢,你可以在doctrine中完成。

看到此答案以供參考: Symfony2, Doctrine2 query - select with IF and COUNT

+0

編寫查詢不是問題,因爲爭論Doctrine理解如何處理數據。我希望它填充實體字段。如果可能的話,我希望避免特殊的標量查詢和數據傳輸。看來它可能不是,唉。 – 2014-08-29 16:18:42

0

可以運行類似DQL:

SELECT p place, COUNT(u) cnt FROM YourBundle:Place p 
       LEFT JOIN p.users u 

注意,導致陣列元件的形式爲(各是一個數組):

array(
'place' => your hydrated object (in your case the place), 
'cnt' => your aggregated field (in your case the number of users), 
) 
+0

這是令人沮喪的,因爲我不希望它是分開的。我希望Doctrine能夠理解如何將它作爲實體字段填充,而不會像查詢方式那麼昂貴。 – 2014-08-29 16:17:05

+0

你希望學說太聰明;)無論如何,你理想的解決方案使用兩個查詢,但我只使用1.我可以問是什麼問題,這兩個單獨的密鑰? – 2014-08-29 19:57:42

+1

問題是我正在返回要被序列化的實體。現在我有一些其他的隨機值,它不是*某人必須處理的實體的一部分。因此,無論是現在循環遍歷所有結果並重新組織數據以使其合理化,還​​是我的客戶端都會遇到一種笨拙的體驗,即Place實體的集合不僅僅是Place實體的集合,它是一個數組的集合,其中一個鍵是地方,然後N個其他鍵是領域我不夠聰明,能夠使主義發揮良好。當然不是一場災難,但我永遠在尋找更好的方式! – 2014-08-29 23:44:00

相關問題