You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已知父/子分类ID时如何查询所有关联父子分类及对应商品

问题分析

你现有代码models = models.Where(i => i.Category.SubCategories.Select(i => i.Id).Contains(catid));的逻辑是匹配「商品所属分类的直接子分类ID包含目标catid」的商品,既没有覆盖目标分类自身、所有层级的递归子分类,逻辑方向也和需求不符,因此结果不符合预期。

实现方案

根据你的两个需求,优先提供适配中小数据量的内存递归方案,分类数据量极大的场景可以替换为数据库层面的递归CTE方案。

第一步:提前写好两个递归工具方法

注:如果你的实体类ID属性是大写Id,请对应调整代码中的属性名

// 递归获取指定分类ID的自身 + 所有子孙分类ID
private IEnumerable<long> GetAllSubCategoryIds(long catId, List<Category> allCategories)
{
    var result = new List<long> { catId };
    var childIds = allCategories.Where(c => c.ParentId == catId).Select(c => c.id).ToList();
    foreach (var childId in childIds)
    {
        result.AddRange(GetAllSubCategoryIds(childId, allCategories));
    }
    return result;
}

// 递归获取指定分类ID的自身 + 所有祖先分类ID
private IEnumerable<long> GetAllParentCategoryIds(long catId, List<Category> allCategories)
{
    var result = new List<long> { catId };
    var currentCat = allCategories.FirstOrDefault(c => c.id == catId);
    while (currentCat?.ParentId != null)
    {
        result.Add(currentCat.ParentId.Value);
        currentCat = allCategories.FirstOrDefault(c => c.id == currentCat.ParentId.Value);
    }
    return result;
}

需求1:按指定分类ID查询自身+所有子分类下的全部商品

// 先全量加载分类数据(分类量级过万的场景建议替换为CTE方案)
var allCategories = dbContext.Categories.ToList();
// 拿到所有需要匹配的分类ID
var targetCatIds = GetAllSubCategoryIds(catid, allCategories).Distinct().ToList();
// 过滤商品
models = models.Where(p => p.CategoryId.HasValue && targetCatIds.Contains(p.CategoryId.Value));

需求2:按子分类ID查询所有上级父分类+下级子分类的关联数据

var allCategories = dbContext.Categories.ToList();
// 合并祖先和后代分类ID
var parentIds = GetAllParentCategoryIds(childCatId, allCategories);
var subIds = GetAllSubCategoryIds(childCatId, allCategories);
var allRelatedCatIds = parentIds.Union(subIds).Distinct().ToList();
// 过滤对应关联商品即可
models = models.Where(p => p.CategoryId.HasValue && allRelatedCatIds.Contains(p.CategoryId.Value));

大数据量场景优化(以SQL Server为例)

如果分类量级过万,内存递归性能较差,可以直接用递归CTE查询,性能更高:

var products = dbContext.Products.FromSqlInterpolated($@"
WITH RecursiveCte AS
(
    SELECT id FROM Categories WHERE id = {catid}
    UNION ALL
    SELECT c.id FROM Categories c
    INNER JOIN RecursiveCte rc ON c.ParentId = rc.id
)
SELECT p.* FROM Products p
INNER JOIN RecursiveCte rc ON p.CategoryId = rc.id
").ToList();

内容的提问来源于stack exchange,提问作者nabi mohammadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 20:06:03