如何使用JavaScript递归遍历Node.js环境下Mongoose不限层级分类树形结构
实现不限层级分类树形结构的方案
最优方案:全量查询+内存组装(推荐)
该方案仅需1次数据库查询,避免N+1查询性能问题,不受分类层数限制,时间复杂度为O(n),性能远高于递归查询数据库的方案。
async function getCategoryTree() { // 1. 一次性查询全部分类数据 const allCategories = await Category.find().lean() // 2. 初始化_id到分类对象的映射、根分类数组 const categoryMap = {} const rootCategories = [] // 先把所有分类存入映射表,同时提前为每个分类初始化children子数组 allCategories.forEach(cat => { categoryMap[cat._id.toString()] = { ...cat, children: [] } }) // 3. 遍历所有分类,组装父子层级关系 allCategories.forEach(cat => { const currentCat = categoryMap[cat._id.toString()] if (cat._mother_category) { // 存在父分类,将当前分类推入父分类的children数组 const motherCat = categoryMap[cat._mother_category.toString()] if (motherCat) { motherCat.children.push(currentCat) } } else { // 无父分类,属于根层级节点 rootCategories.push(currentCat) } }) return rootCategories } // 调用示例 const categoryTree = await getCategoryTree() console.log(categoryTree) // 输出完整的不限层级分类树
返回的rootCategories即为完整的多层级分类树,每个节点的children数组存储了它的所有子分类,支持任意深度的层级结构。
备选方案:递归查询数据库(仅适合数据量极小的场景)
如果分类数据量特别大、全量查询内存占用过高,可以采用递归查询方案,缺点是分类层数越多数据库查询次数越多,性能较低。
async function getCategoryWithChildren(parentId = null) { const query = parentId ? { _mother_category: parentId } : { _mother_category: { $exists: false } } const categories = await Category.find(query).lean() // 递归查询每个分类的子分类 for (const cat of categories) { cat.children = await getCategoryWithChildren(cat._id) } return categories } // 调用示例 const categoryTree = await getCategoryWithChildren()
内容的提问来源于stack exchange,提问作者eduardo
相关产品推荐
相关产品推荐

