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

如何从含parent_id的地理数据生成层级化URL?

问题描述

现有一张混合存储国家、城市、次级城市等地理数据的表,示例数据如下:

Name | id | parent_id
1) united kingdom | 1 | 0;
2) london | 2 | 1;
3) south london | 3 | 2;

需为每个城市生成层级化URL,例如伦敦南部的URL为:

/united-kingdom/london/south-london

目前通过以下代码从服务获取Geo对象列表,每个对象包含id和parentId(国家的parentId为null),请教如何基于这些数据创建上述层级结构?

var geoSolution = await _geoService.GetGeoChildren(selectedCountry, culture, cancellationToken);   
foreach (var geo in geoSolution.Value ?? Enumerable.Empty<Geo>())
{
    if (geo.ParentId == null) continue; 
    sitemapList.Add(new SitemapHtml(geo.GeoName ?? string.Empty, GetPrefix(geo.Name ?? string.Empty, product ?? ""))
    {
        Links = await GetSitemapLinksForGeo(urlSections, geo, cancellationToken, true)
    });
}

return sitemapList.OrderBy(x => x.Name).ToList();

注:geoSolution返回的Geo对象列表中,国家类型的对象parentId为null。

解决方案

要生成层级化URL,核心是为每个Geo对象回溯完整的父级链,将链中每个节点的名称转换为URL友好格式后拼接成路径。

1. 构建Geo对象映射字典

先把所有Geo对象存入字典,方便通过id快速查找父节点:

var allGeoItems = geoSolution.Value ?? Enumerable.Empty<Geo>();
// 以Geo的Id为键,建立快速查找映射
var geoById = allGeoItems.ToDictionary(g => g.Id, g => g);

2. 编写层级URL生成方法

用迭代方式向上遍历父节点,收集并格式化路径段,避免递归栈溢出问题:

private string BuildHierarchicalUrl(Geo geo, Dictionary<int, Geo> geoById)
{
    var pathSegments = new List<string>();
    var currentGeo = geo;

    // 从当前节点向上遍历至根节点(国家)
    while (currentGeo != null)
    {
        // 将名称转为URL友好格式:小写、空格替换为连字符,跳过空值
        var urlSegment = currentGeo.Name?.Trim().ToLower().Replace(" ", "-") ?? string.Empty;
        if (!string.IsNullOrEmpty(urlSegment))
        {
            pathSegments.Add(urlSegment);
        }

        // 终止条件:当前是国家节点(ParentId为null)
        if (currentGeo.ParentId == null)
        {
            break;
        }

        // 查找父节点
        geoById.TryGetValue(currentGeo.ParentId.Value, out currentGeo);
    }

    // 反转路径段,得到从根到子的顺序
    pathSegments.Reverse();
    // 拼接成完整URL路径
    return "/" + string.Join("/", pathSegments);
}

3. 集成到现有代码中

修改原有循环逻辑,调用生成方法替换原有的GetPrefix:

var geoSolution = await _geoService.GetGeoChildren(selectedCountry, culture, cancellationToken);   
var allGeoItems = geoSolution.Value ?? Enumerable.Empty<Geo>();
var geoById = allGeoItems.ToDictionary(g => g.Id, g => g);

foreach (var geo in allGeoItems)
{
    if (geo.ParentId == null) continue; // 跳过国家节点,仅处理城市及次级节点
    
    // 生成层级化URL
    var hierarchicalUrl = BuildHierarchicalUrl(geo, geoById);
    
    sitemapList.Add(new SitemapHtml(geo.GeoName ?? string.Empty, hierarchicalUrl)
    {
        Links = await GetSitemapLinksForGeo(urlSections, geo, cancellationToken, true)
    });
}

return sitemapList.OrderBy(x => x.Name).ToList();

注意事项

  • 若GetPrefix有其他业务逻辑,可将层级URL与原有前缀拼接,按需调整
  • 需处理名称为空的极端情况,避免生成无效的URL段
  • 迭代方式比递归更适合大数据量场景,防止栈溢出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:10:18