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

如何在Node.js中处理无限层级子分类数组并插入数据库

问题

需要将包含无限层级子分类的Payload数据插入数据库,每个分类对象包含name字段和child_categories子数组,要求每条分类记录携带其父分类的parent_category_id。当前代码仅能处理固定层级的分类插入,无法适配无限层级场景,如何循环处理这类数组完成数据库插入?

Payload结构

{
    "name": "food",
    "child_categories": [
        {
            "name": "non-frozen",
            "child_categories": [
               {
                   "name":"non-branded",
                    "child_categories": [
                        {
                            "name":"food-grains",
                            "child_categories": [
                                {
                                   "name":"rice"
                                },
                                {
                                    "name": "atta"
                                },
                                {
                                    "name": "maida"
                                },
                                {
                                    "name": "sooji"
                                },
                                {
                                    "name":"ragi"
                                },
                                {
                                    "name": "jower"
                                },
                                {
                                    "name": "bajra"
                                }
                            ]
                        },
                        {
                            "name":"salt&spices",
                             "child_categories": [
                                 {
                                     "name":"whole-spices"
                                 },
                                 {
                                     "name":"grounded-spices"
                                 }
                             ]
                        },
                        {
                            "name":"dried-condiments",
                             "child_categories": [
                                 {
                                     "name":"salt"
                                 },
                                 {
                                     "name":"powders"
                                 },
                                 {
                                     "name":"sugar"
                                 },
                                 {
                                     "name":"jaggery"
                                 }

                             ]
                        },
                        {
                            "name": "edible-oil&ghee"
                        },
                        {
                            "name": "lentils",
                            "child_categories":[
                                {
                                    "name":"all-dals"
                                },
                                {
                                    "name":"all-rajma"
                                },
                                {
                                    "name":"chanas"
                                },
                                {
                                    "name":"millets"
                                },
                                {
                                    "name":"soya"
                                }
                            ]
                        }

                    ]
               },
               {
                   "name":"branded",
                       "child_categories": [
                        {
                            "name":"food-grains",
                            "child_categories": [
                                {
                                   "name":"rice"
                                },
                                {
                                    "name": "atta"
                                },
                                {
                                    "name": "maida"
                                },
                                {
                                    "name": "sooji"
                                },
                                {
                                    "name":"ragi"
                                },
                                {
                                    "name": "jower"
                                },
                                {
                                    "name": "bajra"
                                }
                            ]
                        },
                        {
                            "name":"salt&spices",
                             "child_categories": [
                                 {
                                     "name":"whole-spices"
                                 },
                                 {
                                     "name":"grounded-spices"
                                 }
                             ]
                        },
                        {
                            "name":"dried-condiments",
                             "child_categories": [
                                 {
                                     "name":"salt"
                                 },
                                 {
                                     "name":"powders"
                                 },
                                 {
                                     "name":"sugar"
                                 },
                                 {
                                     "name":"jaggery"
                                 }

                             ]
                        },
                        {
                            "name": "edible-oil&ghee"
                        },
                        {
                            "name": "lentils",
                            "child_categories":[
                                {
                                    "name":"all-dals"
                                },
                                {
                                    "name":"all-rajma"
                                },
                                {
                                    "name":"chanas"
                                },
                                {
                                    "name":"millets"
                                },
                                {
                                    "name":"soya"
                                }
                            ]
                        },
                        {
                            "name":"snacks&cereals",
                            "child_categories":[
                                {
                                    "name":"biscuits"
                                },
                                {
                                    "name":"cookies"
                                },
                                {
                                    "name":"bhujia"
                                },
                                {
                                    "name":"mixture"
                                }
                            ]
                        },
                        {
                            "name":"packaged-raw",
                            "child_categories":[
                                {
                                    "name":"noodles"
                                },
                                {
                                    "name":"pasta"
                                },
                                {
                                    "name":"macaroni"
                                },
                                 {
                                    "name":"spreads"
                                },
                                 {
                                    "name":"sauces"
                                },
                                 {
                                    "name":"ready-to-eat"
                                },
                                {
                                    "name":"chocs"
                                },
                                {
                                    "name":"pickles&chutney"
                                }
                            ]
                        }

                    ]
               }
            ]
        }
      
    ]
}

数据库存储示例

{
  "_id": "1",
  "parent_category_id": null, // 一级分类
  "name":"food"
}

{
  "_id":2,
  "parent_category_id": 1,
  "name": "non-frozen"
}

{  
  "_id": 3,
  "parent_category_id": 2,
  "name": "non-branded"
}
{
  "_id": 4,
  "parent_category_id": 3,
  "name": "food-grains"
}

// 以此类推...

现有代码(仅支持固定层级)

let payload = req.payload
let obj1 = {
    "name": payload.name,
    "parent_category_id": null,
    "created_by": userId,
    "updated_by": userId
}
let parent_category = await Category.create(obj1)
if (!!payload.childCategories){
    payload.childCategories.forEach(async item => {
        if(!!item){
            let obj2 = {
                "name": item.name,
                "parent_category_id": parent_category._id,
                "created_by": userId,
                "updated_by": userId
            }
            let parent_category1 = await Category.create(obj2)
            if (!!item.childCategories){
                payload.childCategories.forEach(async item1 => {
                    let obj3 = {
                        "name": item1.name,
                        "parent_category_id": parent_category1._id,
                        "created_by": userId,
                        "updated_by": userId
                    }
                    let parent_category2 = await Category.create(obj3)
                })
            }
        }
    })
}

解决方案

核心思路是用递归函数处理无限层级的嵌套分类,递归函数负责插入当前分类,并自动递归处理其所有子分类。同时修复原代码中异步流程失控、硬编码层级的问题。

修正后的代码

// 递归插入分类的核心函数
async function insertCategories(category, parentId, userId) {
    // 插入当前分类
    const categoryDoc = await Category.create({
        name: category.name,
        parent_category_id: parentId,
        created_by: userId,
        updated_by: userId
    });

    // 处理当前分类的子分类
    if (category.child_categories && category.child_categories.length > 0) {
        // 使用for...of替代forEach,确保异步流程顺序执行
        for (const child of category.child_categories) {
            await insertCategories(child, categoryDoc._id, userId);
        }
    }
}

// 调用入口
async function handleCategoryInsert(req) {
    const payload = req.payload;
    const userId = req.user._id; // 根据实际业务获取用户ID
    await insertCategories(payload, null, userId);
    return { message: "所有分类插入完成" };
}

代码说明

  1. 递归函数逻辑:

    • 每次调用先插入当前分类,获取生成的_id
    • 若当前分类存在子分类,就遍历每个子分类,递归调用自身,将当前分类的_id作为子分类的parent_category_id
    • 无论嵌套多少层,都会逐层处理直到所有分类插入完成
  2. 异步流程修复:

    • 用for...of替代forEach,forEach无法配合async/await保证顺序,for...of可以确保每个子分类插入完成后再处理下一个,避免数据库插入顺序混乱
  3. 原代码问题修复:

    • 去掉硬编码的层级逻辑,适配任意嵌套深度
    • 修正了第二层遍历错误的数组(原代码错误遍历根分类的子数组,而非当前分类的子数组)
    • 统一异步流程控制,避免并行插入导致的异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:40:32