C# 使用Queue高效检索树行数据符合条件的数据,并返回完整树形数据示例

最近有项目需要加载大型树数据,数据大概3W条

后端使用C# NET6 

前端使用Vue3 elementuiplus 虚拟tree =》解决大型树数据加载

遇到的问题是后端在检索数据时,要返回匹配数据的完整树目录

1.因为单条数据没有存放完整路径,需要通过父级ID逐级查找组装,导致性能急剧下降

2.数据包数据20M左右,前端下载受带宽影响也变慢

下面来说问题1

采用BOM树缓存,筛选时使用Queue来处理遍历数据加载符合条件的树数据如下

/// <summary>
        /// 过滤与重建树数据
        /// </summary>
        /// <param name="tree"></param>
        /// <param name="predicate"></param>
        /// <param name="qualifiedNodes"></param>
        /// <returns></returns>
        public static List<BOM_DetailTree> FilterAndRebuildTreeOptimized(List<BOM_DetailTree> tree, Func<BOM_DetailTree, bool> predicate, HashSet<long> qualifiedNodes)
        {
            var result = new List<BOM_DetailTree>();
            // 使用队列来处理树的广度优先遍历
            var queue = new Queue<(BOM_DetailTree Node, List<BOM_DetailTree> Result)>();
            queue.Enqueue((tree.FirstOrDefault(n => n.ParentID == null || n.ParentID == 0), result));
            //while (stack.Count > 0)
             while (queue.Count > 0)
                {
                    var (currentNode, currentResult) = queue.Dequeue();

                // 如果当前节点满足条件或其子节点中有满足条件的,添加到结果树
                if (predicate(currentNode) || HasQualifiedChild(currentNode, predicate))
                {
                    var newNode = new BOM_DetailTree
                    {
                        Id = currentNode.Id,
                        ProjectCode = currentNode.ProjectCode,
                        MaterialCode = currentNode.MaterialCode,
                        MaterialName = currentNode.MaterialName,
                        ParentID = currentNode.ParentID,
                        ParentCode = currentNode.ParentCode,
                        MaterialCategory = currentNode.MaterialCategory,
                        QtyPerPiece = currentNode.QtyPerPiece,
                        UnAllotNum = currentNode.UnAllotNum,
                        ManualTotalQuantity = currentNode.ManualTotalQuantity,
                        IsPart = currentNode.IsPart,
                        IsStandard = currentNode.IsStandard,
                        PublishedStatus = currentNode.PublishedStatus,
                        IsUrgency = currentNode.IsUrgency,
                        NodeLevel = currentNode.NodeLevel,
                        IsSupplement = currentNode.IsSupplement,
                        AlterationStatusLable = currentNode.AlterationStatusLable,
                        IsShowTooltip = currentNode.IsShowTooltip,
                        IsAddBOM = currentNode.IsAddBOM,
                    };
                    currentResult.Add(newNode);

                    // 添加当前节点的子节点到栈中
                    if (currentNode.Children != null)
                    {
                        foreach (var child in currentNode.Children)
                        {
                           // stack.Push((child, newNode.Children ?? new List<BOM_DetailTree>()));
                            queue.Enqueue((child, newNode.Children ?? new List<BOM_DetailTree>()));
                        }
                    }
                }
            }

            return result;
        }


        /// <summary>
        /// 判断节点与子节点是否有匹配
        /// </summary>
        /// <param name="node"></param>
        /// <param name="filterPredicate"></param>
        /// <returns></returns>
        private static bool HasQualifiedChild(BOM_DetailTree node, Func<BOM_DetailTree, bool> filterPredicate)
        {
            if (filterPredicate(node))
            {
                return true;
            }

            if (node.Children != null)
            {
                foreach (var child in node.Children)
                {
                    if (HasQualifiedChild(child, filterPredicate))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
 

使用时

 Func<BOM_DetailTree, bool> filterPredicate = node =>
                node.PublishedStatus == 1;
                var qualifiedNodes = new HashSet<long>();
                var newTree= FilterAndRebuildTreeOptimized(cacheTree, filterPredicate, qualifiedNodes);

过滤效率毫秒级。

第二个问题

Startup添加响应数据压缩

 // 添加响应压缩服务
            services.AddResponseCompression(options =>
            {
                options.EnableForHttps = true;
                options.Providers.Add<GzipCompressionProvider>();
                options.Providers.Add<BrotliCompressionProvider>();
                options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                    new[] {  "application/json" });
            });

   app.UseResponseCompression();

优化后即时数据大的情况基本在2S以内响应结果,满足使用

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

11eleven

你的鼓励是我创作的动力 !

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值