我有两个实体,User和Place,并且它们之间有多对多的关系,以便于用户喜欢某个地方的概念。
作为该功能的一部分,我希望Place实体包含一个字段,该字段为我提供了已经收藏它的用户总数。我自己不需要用户实体。
阅读文档后,我找到了几种解决方案,但我并不特别喜欢它们。
汇总字段
使用此解决方案,我只需在Venue实体上定义一个整数字段,在添加和删除收藏夹时更新该字段。因此,该值不是在运行中计算的,而是与任何其他字段一样被检索。
我不喜欢这种方法,因为并发存在问题,这使得在代码中管理这个概念变得非常复杂。
急切加载
使用这种方法,我会急切地将关系加载为双向关联,以便Place将加载每个在初始查询过程中已经收藏它的用户实体。为了获得计数,我只是询问集合的计数()。
这样可以减少查询次数,但检索到的数据量太多,而且随着时间的推移不能很好地扩展。
延迟加载
这就是我目前正在使用的内容。它与Eager Loading解决方案类似,我确保关系是双向的,只是询问集合的count(),但使用额外的延迟获取模式doctrine足够智能,只发出COUNT()查询而不是检索与Place实体关联的整个用户列表。
这里的缺点是,如果我加载N Place实体,我需要N + 1个查询,因为每个Place都会发出一个单独的COUNT()查询。
理想解决方案
我理想的解决方案是找到一种方法来告诉Doctrine执行第一个查询来加载集合,然后第二个查询来加载集合中ID的所有计数,然后填充各自实体中的字段。 / p>
我还没有找到办法轻松做到这一点。
有没有人有任何这方面的例子,或者是否有其他解决方案来解决我可能会忽略的问题?
答案 0 :(得分:0)
如果您知道如何在sql中编写查询,则可以在doctrine中进行。
请参阅此答案以供参考: Symfony2, Doctrine2 query - select with IF and COUNT
答案 1 :(得分: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),
)