代码之家  ›  专栏  ›  技术社区  ›  RageZ

电子商务、分类产品和分类浏览

  •  1
  • RageZ  · 技术社区  · 15 年前

    我正在为一个客户建立一个电子商务网站,项目经理提出了一些奇怪的想法,我正在努力实现他卖给客户的东西。

    下面是我的主要问题和系统设置的快速总结:产品在类别中,类别可能是另一个类别的子类别。所以这个分类是以树的形式出现在网站的左侧边栏上。

    用户可以浏览任何类别,甚至是非“叶”类别,如果用户单击非叶类别A列表,类似的列表应显示为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)中创建一个大类别,我知道根据经验长在语句中执行不好。

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

    2 回复  |  直到 12 年前
        1
  •  6
  •   Bill Karwin    15 年前

    你可以用 物化道路 设计。目录路径是物化路径的一个例子。也就是说,串联在一起的一系列祖先值,用一些字符(“/”或“,”是常见的)分隔它们。

    因此,您可能有以下类别:

    +---------------------------------------------+
    | 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/%' 是真的,因此包括了墙壁卫星。对于音频的任何其他子类别也是如此。


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

    所以如果你选择“扬声器”,你会看到:

    • 数码产品
      • 音频
        • 扬声器
      • 计算机
      • 数码相机

    但你不想要电脑或数码相机的后代(例如,扬声器的“表亲”)。

    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;
    

    我使用一个技巧来检测叔叔:在剥离最后一个元素后比较路径。要执行此操作,请反转字符串,然后剥离 第一 元素。这至少在MySQL和MS SQL Server中有效,但是 REVERSE() 不是标准的,可能不适用于其他品牌的RDBMS。

    请注意,对于 cat_path 在这种情况下,子串偏移量也应该增加。

        2
  •  1
  •   APC    15 年前

    从性能的角度来看,这是一个糟糕的设计。如果客户不小心单击了TopPermost类别,您将执行整个库存的查询。这可能需要不可接受的时间。用网络术语来说,这意味着客户失去耐心,点击对手的网站,然后 不再访问您的网站 .

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

    我也会把树导航的整个概念作为一种方法来考虑。让你的客户玩一个“猜猜我们如何清点库存”的游戏有点过分。除其他外,在许多领域中,产品可以属于多个类别,因此在层次结构中拟合它们是一个任意的过程。至少您应该有一个支持将产品分配给多个叶类别的数据模型。(这可能取决于您所销售产品的性质和类别的粒度)。

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

    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
    

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