Golang电商项目中的分类模块实现

Golang电商项目中的分类模块实现 大家好,

我正在开发一个电子商务项目,需要帮助处理产品的分类部分。

分类表可能包含以下字段: id - parent - title - level

在函数参数中,我通过查询获取父级UUID并返回该父级的所有子分类。但我不知道如何检测子分类的子分类以及如何识别父级,以便在父子层级结构中将产品关联到相应的分类。以下是我用于返回父级所有子分类的查询:

func GetChildrenCategories(db *sql.DB, w http.ResponseWriter, r *http.Request) {

	ctx := context.Background()
	type ParentID struct {
		ParentUUID uuid.UUID `json:"parentuuid"`
	}

	parentID := ParentID{}

	decoder := json.NewDecoder(r.Body)
	if err := decoder.Decode(&parentID); err != nil {
		utils.RespondError(w, http.StatusBadRequest, err.Error())
		return
	}
	defer r.Body.Close()

	query := `
WITH RECURSIVE subordinates AS (
	SELECT
	   id,
	   parent,
	   title,
	   level
	FROM
	   categories
	WHERE
	parent = $1 
	UNION
	   SELECT
		  e.id,
		  e.parent,
		  e.title,
		  e.level
	   FROM
	   categories e
	   INNER JOIN subordinates s ON s.id = e.parent
 ) SELECT
	*
 FROM
	subordinates;
`

	rows, err := db.QueryContext(ctx, query, parentID.ParentUUID)

	if err != nil {
		panic(err)
	}

	categories := make([]model.Category, 0)
	for rows.Next() {
		var category model.Category
		if err := rows.Scan(&category.Id, &category.Parent, &category.Title, &category.Level); err != nil {

		}

		categories = append(categories, category)
	}

	utils.RespondJSON(w, http.StatusOK, categories)
}

请帮助我修复这个部分。


更多关于Golang电商项目中的分类模块实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang电商项目中的分类模块实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在电商项目中实现递归分类查询,你的思路是正确的。以下是优化后的实现,包含完整的错误处理和更清晰的结构:

func GetChildrenCategories(db *sql.DB, w http.ResponseWriter, r *http.Request) {
    ctx := context.Background()
    
    type Request struct {
        ParentUUID uuid.UUID `json:"parentuuid"`
    }
    
    var req Request
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        utils.RespondError(w, http.StatusBadRequest, "Invalid request body")
        return
    }
    defer r.Body.Close()
    
    // 递归查询获取所有子分类
    query := `
    WITH RECURSIVE category_tree AS (
        SELECT 
            id,
            parent,
            title,
            level,
            1 as depth
        FROM categories
        WHERE parent = $1
        
        UNION ALL
        
        SELECT 
            c.id,
            c.parent,
            c.title,
            c.level,
            ct.depth + 1
        FROM categories c
        INNER JOIN category_tree ct ON c.parent = ct.id
    )
    SELECT id, parent, title, level, depth
    FROM category_tree
    ORDER BY depth, title`
    
    rows, err := db.QueryContext(ctx, query, req.ParentUUID)
    if err != nil {
        utils.RespondError(w, http.StatusInternalServerError, "Database query failed")
        return
    }
    defer rows.Close()
    
    // 构建分类树结构
    type CategoryWithDepth struct {
        model.Category
        Depth int `json:"depth"`
    }
    
    categories := make([]CategoryWithDepth, 0)
    for rows.Next() {
        var cat CategoryWithDepth
        if err := rows.Scan(&cat.Id, &cat.Parent, &cat.Title, &cat.Level, &cat.Depth); err != nil {
            utils.RespondError(w, http.StatusInternalServerError, "Data scanning failed")
            return
        }
        categories = append(categories, cat)
    }
    
    if err = rows.Err(); err != nil {
        utils.RespondError(w, http.StatusInternalServerError, "Row iteration error")
        return
    }
    
    utils.RespondJSON(w, http.StatusOK, categories)
}

如果需要构建树形结构返回,可以添加以下函数:

func BuildCategoryTree(categories []CategoryWithDepth) []map[string]interface{} {
    // 按父级分组
    childrenMap := make(map[uuid.UUID][]map[string]interface{})
    
    for _, cat := range categories {
        node := map[string]interface{}{
            "id":    cat.Id,
            "title": cat.Title,
            "level": cat.Level,
        }
        childrenMap[cat.Parent] = append(childrenMap[cat.Parent], node)
    }
    
    // 递归构建树
    var buildTree func(parentID uuid.UUID) []map[string]interface{}
    buildTree = func(parentID uuid.UUID) []map[string]interface{} {
        children := childrenMap[parentID]
        for i := range children {
            children[i]["children"] = buildTree(children[i]["id"].(uuid.UUID))
        }
        return children
    }
    
    return buildTree(uuid.Nil) // 从根节点开始
}

对于产品分类关联,可以这样查询:

func GetProductsByCategory(db *sql.DB, categoryID uuid.UUID) ([]model.Product, error) {
    query := `
    WITH RECURSIVE category_hierarchy AS (
        SELECT id FROM categories WHERE id = $1
        UNION ALL
        SELECT c.id FROM categories c
        INNER JOIN category_hierarchy ch ON c.parent = ch.id
    )
    SELECT p.* FROM products p
    INNER JOIN product_categories pc ON p.id = pc.product_id
    WHERE pc.category_id IN (SELECT id FROM category_hierarchy)`
    
    rows, err := db.Query(query, categoryID)
    if err != nil {
        return nil, err
    }
    defer rows.Close()
    
    var products []model.Product
    for rows.Next() {
        var p model.Product
        if err := rows.Scan(&p.ID, &p.Name, &p.Price, &p.Description); err != nil {
            return nil, err
        }
        products = append(products, p)
    }
    
    return products, nil
}

这个实现提供了完整的递归分类查询,包含深度信息,并支持产品与分类的关联查询。

回到顶部