Symfony 6 Doctrine Repository查询问题:按主分类各取5篇文章
解决Symfony 6中每个主分类下获取5篇产品的问题
方法一:利用窗口函数(适用于MySQL 8+/PostgreSQL等支持窗口函数的数据库)
这种方法效率更高,一次查询就能完成需求。假设你的实体关系如下:
MainCategory(主分类):包含多个SubCategorySubCategory(子分类):属于一个MainCategory,包含多个ProductProduct(产品):属于一个SubCategory
在你的ProductRepository中添加如下方法:
use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; public function findLastFivePerMainCategory() { $qb = $this->createQueryBuilder('p') ->select('p, sc, mc') ->join('p.subCategory', 'sc') ->join('sc.mainCategory', 'mc') ->addSelect('ROW_NUMBER() OVER (PARTITION BY mc.id ORDER BY p.createdAt DESC) AS rn') ->having('rn <= 5') ->orderBy('mc.id', 'ASC') ->addOrderBy('p.createdAt', 'DESC'); $query = $qb->getQuery(); // 处理返回结果,整理成按主分类分组的结构 $results = $query->getResult(); $groupedResults = []; foreach ($results as $item) { $mainCategory = $item[0]->getSubCategory()->getMainCategory(); $groupId = $mainCategory->getId(); if (!isset($groupedResults[$groupId])) { $groupedResults[$groupId] = [ 'mainCategory' => $mainCategory, 'products' => [] ]; } $groupedResults[$groupId]['products'][] = $item[0]; } return array_values($groupedResults); }
说明:
ROW_NUMBER() OVER (PARTITION BY mc.id ORDER BY p.createdAt DESC)按主分类ID分组,每组内按产品创建时间倒序给产品编号having('rn <= 5')筛选出每组的前5条数据- 最后通过循环把结果整理成按主分类分组的结构,方便业务层直接使用
方法二:遍历主分类分别查询(兼容所有数据库)
如果你的数据库不支持窗口函数,可以先获取所有主分类,再逐个查询对应主分类下的最新5篇产品:
首先在ProductRepository中添加单分类查询方法:
use App\Entity\MainCategory; public function findLastFiveByMainCategory(MainCategory $mainCategory) { return $this->createQueryBuilder('p') ->join('p.subCategory', 'sc') ->where('sc.mainCategory = :mainCategory') ->setParameter('mainCategory', $mainCategory) ->orderBy('p.createdAt', 'DESC') ->setMaxResults(5) ->getQuery() ->getResult(); }
然后在业务层(如Controller或Service)中调用:
// 注入MainCategoryRepository和ProductRepository $mainCategories = $this->mainCategoryRepository->findAll(); $results = []; foreach ($mainCategories as $mc) { $results[] = [ 'mainCategory' => $mc, 'products' => $this->productRepository->findLastFiveByMainCategory($mc) ]; }
说明:
- 这种方法兼容性强,无需数据库支持窗口函数
- 若主分类数量较多,会执行多次查询,性能略低于窗口函数方案
注意事项
- 确保实体间的关联映射配置正确,比如
SubCategory中存在指向MainCategory的关联字段,且ORM注解配置无误 - 可根据实际需求调整
orderBy的排序字段(如updatedAt或自定义排序字段)
内容的提问来源于stack exchange,提问作者user2702355
相关产品推荐
相关产品推荐

