【问题标题】:ECommerce, products in category and category browsing电子商务、分类中的产品和分类浏览
【发布时间】:2009-10-29 03:03:35
【问题描述】:

我正在为客户建立一个 EC 网站,项目经理提出了一些奇怪的想法,我正在努力实际实施他向客户销售的内容。

这是我的主要问题和系统设置的快速总结:产品在类别内,类别可能是另一个类别的子类别。因此,该类别在网站的左侧边栏上显示为树。

用户可以浏览任何类别,甚至是非“叶”类别,如果用户单击非叶类别,则应在 1 级类别上显示类似的列表(同样适用于 2 级类别):

big category 1
 category level ( 3 or 2 )
  product 1
  product 2
  product 3
 category level ( 3 or 2 ) 

这些东西还应该有一些分页,并出现在每个页面上的 5 个产品上。另外,类别应该以它们出现在左侧菜单中的相同方式排序......我的数据库方案是这样的:

+-------------+    +-------------+
+ category    +    + product     +
+-------------+    +-------------+
+ category_id +    + product_id  +
+ parent_id   +    + category_id + 
+-------------+    +-------------+

我真的不知道我应该如何编写 SQL 以确保产品按应有的顺序显示(比如订购产品和类别有菜单)。

我还关心整个设置的性能,如果用户选择非“叶子”类别,我将不得不搜索所有子类别并在 (id1, id2, id3) 中创建一个大类别,我知道根据经验,长 IN 语句表现不佳。

如果有人遇到相同的设计/问题,并有一些建议如何制作,我将不胜感激。

【问题讨论】:

    标签: php database-design e-commerce


    【解决方案1】:

    您可以使用 Materialized Path 设计。目录路径是物化路径的示例。也就是说,一系列祖先值,连接在一起,用一些字符(“/”或“,”是常见的)分隔它们。

    所以你可能有类别:

    +---------------------------------------------+
    | cat_id | Name            | cat_path | depth |
    +---------------------------------------------+
    |    1   | Electronics     | 1/       |   1   |
    |    2   | Digital cameras | 1/2/     |   2   |
    |    3   | SLR cameras     | 1/2/3/   |   3   |
    |    4   | Audio           | 1/4/     |   2   |
    |    5   | Speakers        | 1/4/5/   |   3   |
    |    6   | Wall Satellites | 1/4/5/6/ |   4   |
    |    7   | Computers       | 1/7/     |   2   |
    +---------------------------------------------+
    

    现在,如果您想要音频下的所有产品,您可以执行如下查询:

    SELECT p.*, pc.*
    FROM Products p JOIN Categories pc ON (p.cat_id = pc.cat_id)
    JOIN Categories c ON (pc.cat_path LIKE c.cat_path||'%')
    WHERE c.name = 'Audio';
    

    例如,'1/4/5/6' LIKE '1/4/%' 为真,因此包含 Wall Satellites。对于任何其他音频子类别也是如此。


    关于菜单渲染的问题:我假设您希望菜单渲染: - 所选类别的所有祖先 - 所选类别的祖先的所有兄弟姐妹

    因此,如果您选择“演讲者”,您会看到:

    • 电子产品
      • 音频
        • 演讲者
      • 计算机
      • 数码相机

    但您不想要计算机或数码相机的后代(即扬声器的“表亲”)。

    SELECT uncle.name, uncle.depth
    FROM Categories chosen
    JOIN Categories ancestor ON (chosen.cat_path LIKE ancestor.cat_path||'%')
    JOIN Categories uncle ON (ancestor.depth = uncle.depth
      AND SUBSTRING(REVERSE(ancestor.cat_path), 3, 100) = SUBSTRING(REVERSE(uncle.cat_path), 3, 100))
    WHERE chosen.name = 'Speakers'
    ORDER BY uncle.depth, uncle.name;
    

    我正在使用一个技巧来检测叔叔:在剥离最后一个元素之后比较路径。为此,反转字符串,然后剥离 first 元素。这至少在 MySQL 和 MS SQL Server 中应该可以工作,但 REVERSE() 不是标准的,可能无法移植到其他品牌的 RDBMS。

    请注意,您可能应该允许cat_path 中的每个元素多于一位,在这种情况下,子字符串偏移量也应该增加。

    【讨论】:

    • 非常感谢,是的,它简化了事情,只是一个关于该设计的快速子问题,您如何实现类别菜单呈现?就像在
      的层次结构中显示事物
    • 感谢您的大力帮助,我想我可以从现在开始管理它 ;-)
    • 这可能是旧的,但值得更多关注,好的解决方案和性能方面它的优秀,例如不需要进行树遍历!
    【解决方案2】:

    从性能的角度来看,这是一个糟糕的设计。如果客户不小心点击了最上面的类别,您将执行整个库存的查询。这可能会花费不可接受的时间。用网络术语来说,这意味着客户失去了耐心,点击了您竞争对手的网站并且再也不会访问您的网站

    当然,过早的优化是万恶之源,但最好避免做完全愚蠢的事情。

    我也会对树导航作为一种方法的整个想法提出异议。要求您的客户玩“猜猜我们如何盘点我们的库存”的游戏有点过分了。除此之外,在许多领域中,产品可以属于多个类别,因此将它们放入层次结构是一个任意过程。至少您可能应该有一个支持将产品分配给多个叶类别的数据模型。 (这可能取决于您销售的产品的性质和类别的粒度)。

    如果你的老板坚持他们的方式,那么你仍然有一些选择来提高查询的性能。例如,您可以有一个表格,其中包含由所有父类别连接的所有产品...

    cat1 product1
    cat1 product2
    cat1 product3
    cat1 product4
    cat1 cat1.1 product1
    cat1 cat1.1 product2
    cat1 cat1.2 product3
    cat1 cat1.2 product4
    cat1 cat1.1 cat1.1.1 product1
    cat1 cat1.1 cat1.1.2 product2
    cat1 cat1.2 cat1.2.1 product3
    cat1 cat1.2 cat1.2.2 product4
    

    您必须通过触发器或作为物化视图或通过其他一些机制来维护它(取决于您的数据库风格提供的内容)。但是与不必为每个客户查询重新组装产品层次结构的性能优势相比,维护它的开销可以忽略不计。此外,您的库存不太可能有那么大的波动性。

    【讨论】:

    • 我同意树结构不是我组织目录的方式。基于标签的系统现在变得流行起来,它们确实允许产品存在于集合中的多个位置。但是你可能需要分层标签。无论如何,OP 并没有要求某人更改需求,而是询问如何实现他的需求,即将类别组织为树。
    • @APC 是的,标签系统会更好,这些东西可能会救我,目录有点小,因为产品真的很贵,而且我可能会对这些数据做一些缓存。我希望能够改变系统的行为方式,但是与客户的协商已经完成并且无法返回,这就是在与客户交谈期间没有开发人员时发生的情况。 @Bill 再次感谢你
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 2023-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多